乐趣区

关于java:知识总结死锁

概念

死锁是指两个或多个以上的过程在执行过程中,因抢夺资源而造成一种 相互期待的景象,若无外力干预那他们都将无奈推动上来。如果资源短缺,过程的资源申请都可能失去满足,死锁呈现的可能性就很低,否则就会因抢夺无限的资源而陷入死锁。

持有本人的锁,还妄图要他人的锁。

死锁产生的 4 个必要条件(缺一不可)

设想你来到巴黎卢浮宫博物馆,想要排队看看《蒙娜丽莎的微笑》:

  • 互斥:一幅画一次只能一个人看。(某个资源只能互斥的应用,例如磁盘、物理内存)
  • 申请放弃:

    1. 申请:张三排队轮到他看蒙娜丽莎的同时,他很贪婪,要看蒙娜丽莎的同时,要看梵高的向日葵(过程在应用已申请资源时,申请应用其余互斥资源)
    2. 放弃:如果不给张三看向日葵,那么张三就不走(过程放弃对已分配资源的占有)
  • 不可剥夺:如果李四正在看向日葵,张三看不了,那么张三就始终堵在蒙娜丽莎后面,不给其他人看(进行曾经申请的资源在没开释前不可被剥夺)
  • 循环期待:李四也不满足于看向日葵,也要同时看蒙娜丽莎,而张三占用了蒙娜丽莎,同时也要看向日葵。导致两人谁也不走,陷入了僵局

死锁预防(毁坏死锁的条件)

通过毁坏死锁的四大必要条件,来预防死锁的产生:

  • 互斥:有些资源自身就是互斥的,无奈扭转,有的时候是代码设计导致的某些变量互斥了。就像这里的画一样,让多集体一起看不就解决了。
  • 申请放弃:一次性调配过程的所有资源。每个人参观必须实现申明好想看的画,而后一次性调配所需的画,不能中途提新的要求。
  • 不可剥夺:过程期待新的资源的时候,将本人的资源先开释,等有新的资源后,操作系统才会唤醒它。让这个想看同时两幅画的人先滚到一边去,等两幅画都空了再给他。
  • 循环期待:将资源编号,每次只能从小到大申请。将向日葵编号为 1,蒙娜丽莎编号为 2,必须先申请参观 1,持有 1 的同时能力申请 2。

解除正在死锁的状态

剥夺资源:从其余过程剥夺足够数量的资源给死锁过程,已解除死锁状态。

撤销过程:能够间接撤销死锁过程,直至有足够的资源可用为止。

死锁代码

咱们创立了一个资源类,而后让两个线程别离 持有本人的锁 同时在尝试获取他人的锁,就会呈现死锁景象。

class HoldLockThread implements Runnable {
    private String lockA;
    private String lockB;

    // 构造函数
    public HoldLockThread(String lockA, String lockB) {
        this.lockA = lockA;
        this.lockB = lockB;
    }
    
    //run 办法
    @Override
    public void run() {synchronized (lockA) {System.out.println(Thread.currentThread().getName()+"本人持有:"+lockA +"尝试取得:"+lockB);
        synchronized (lockB) {System.out.println(Thread.currentThread().getName()+"本人持有:"+lockB +"尝试取得:"+lockA);
        }
    }
}
}
public class DeadLockDemo {public static void main(String[] args) {
        String lockA = "lockA";
        String lockB = "lockB";

        new Thread(new HoldLockThread(lockA, lockB), "线程 1").start();
        new Thread(new HoldLockThread(lockB, lockA), "线程 2").start();}
}

运行后果,发现 main 线程无奈完结

如何排查死锁

  • 通过 jdk 工具 jps、jstack 排查死锁问题
    1. 应用 jps 命令查看运行的程序。这是 jdk 提供的一个查看以后 java 过程的工具。

      // 在 IDEA 关上 Terminal,输出
      jps -l

      咱们能看到 DeadLockDemo 这个类,始终在运行。

    2. 应用 jstack 查看线程堆栈信息。

      jstack 3264            //3264 是下面始终运行的过程的编号

      通过查看最初一行,咱们看到 Found 1 deadlock,即存在一个死锁。

  • 通过 jdk 提供的工具 VisualVM 排查死锁问题

VisuaVM:jdk 提供的一个排查 java 问题的工具。可用监控程序的性能、查看 JVM 配置信息、线程堆栈的信息。

  • 通过 jdk 提供的工具 jconsole 排查死锁问题

jconsole:jdk 提供的一个可视化的工具,不便排查程序的一些问题,如:程序内存溢出、死锁问题等等。

在本地线程处找到咱们的过程,进行连贯。连贯后在窗口中查看线程堆栈信息,有个“检测死锁”的按钮,可用看到程序的死锁信息。

退出移动版