美文网首页
Java死锁分析

Java死锁分析

作者: 金字塔下的小蜗牛 | 来源:发表于2020-04-10 08:34 被阅读0次

    死锁是多进程环境下的一种假死现象,即产生死锁的进程都处于等待状态。只要满足了下面四个必要条件,就有可能产生死锁:

    1. 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
    2. 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
    3. 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
    4. 环路等待条件:是指进程发生死锁后,必然存在一个进程–资源之间的环形链

    一旦产生了死锁,程序将不再往下执行。那么应该怎么分析程序是否产生了死锁呢?本节来介绍一种使用Java Dump分析死锁的方法。

    1.包含死锁的程序

    下面是一段包含死锁的程序:DeadLock.java

    public class DeadLock {
        final Object lockA = new Object();
        final Object lockB = new Object();
        public static void main(String[] args) {
            DeadLock demo = new DeadLock();
            demo.startLock();
        }
        public void startLock(){
            ThreadA a= new ThreadA(lockA,lockB);
            ThreadB b= new ThreadB(lockA,lockB);
            //start threads
            a.start();
            b.start();
        }
    }
    
    class ThreadA extends Thread{
        private Object lockA = null;
        private Object lockB = null;
        public ThreadA(Object a, Object b){
            this.lockA = a;
            this.lockB = b;
        }
        public void run() {
            synchronized (lockA) {
                System.out.println("*** Thread A: ***: Lock A" );
                try {
                    sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lockB) {
                    System.out.println("*** Thread A: ***: Lock B" );
                }
            }
            System.out.println("*** Thread A: ***: Finished" );
        }
    }
    
    class ThreadB extends Thread{
        private Object lockA = null;
        private Object lockB = null;
        public ThreadB(Object a, Object b){
            this.lockA = a;
            this.lockB = b;
        }
        public void run() {
            synchronized (lockB) {
                System.out.println("*** Thread B: ***: Lock B" );
                try {
                    sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lockA) {
                    System.out.println("*** Thread B: ***: Lock A" );
                }
            }
            System.out.println("*** Thread B: ***: Finished" );
        }
    }
    

    说明:以上代码中,有两个共享资源lockA和lockB,同时启动两个线程a和b,其中线程a先申请资源lockA,然后睡3秒,再去申请资源lockB;线程b先申请资源lockB,然后也睡3秒,再去申请资源lockA。当线程a启动并申请到资源lockA然后睡3秒时,这时线程b启动并申请到资源lockB也睡3秒;等线程a睡醒后去申请资源lockB,发现资源lockB被其他线程占用,所以线程a就开始等待;等线程b睡醒后去申请资源lockA,发现资源lockA也被其他线程占用,然后线程b也开始等待。如此这般,a和b就进入了循环等待的死锁状态。

    2.使用JDK的Thread Dump工具分析死锁

    这里介绍一种在Windows和Linux下,使用JDK提供的Thread Dump工具分析死锁的办法。

    1.Windows下使用Thread Dump分析死锁

    (1)编译并执行DeadLock.java程序

    image

    (2)按Ctrl + Break(或者fn + b)分析死锁

    image image

    2.Linux下使用Thread Dump分析死锁

    (1)编译并执行DeadLock.java程序

    image

    (2)使用kill -3 PID分析死锁

    新打开一个终端,查看jps进程号,使用kill -3 PID杀死死锁进程:

    image

    原来的终端窗口会显示检测到的死锁信息:

    image

    死锁分析是一门非常重要的技术手段。使用Thread Dump工具可以方便的检测出程序是否包含死锁。

    本节介绍了Java中使用Thread Dump工具分析死锁的详细过程。祝你玩的愉快!

    相关文章

      网友评论

          本文标题:Java死锁分析

          本文链接:https://www.haomeiwen.com/subject/dmvkdhtx.html