zoukankan      html  css  js  c++  java
  • 检查死锁与Locked ownable synchronizers(转载)

    通过jstack可快速检查线程的死锁信息,用法如下:

    # 获取JVM ID(JAVA 进程ID),通过参数lv可以获取更详细的JAVA方法调用信息
    jps -lv
    # 得到JVM ID后,执行jstack命令,这里假定为123
    # 将结果重定向到文件,更便于查看
    jstack -l 123 >> d:/123.txt
    • 1
    • 2
    • 3
    • 4
    • 5

    翻到页底,可发现明显的死锁信息:

    Java stack information for the threads listed above:
    ===================================================
    "Thread-1":
        at com.mirana.concurrent.LockedOwnThread.run(LockedOwnThread.java:47)
        - waiting to lock <0x000000076c5806f8> (a java.lang.Class for java.lang.Object)
        - locked <0x000000076c636568> (a java.lang.Class for com.mirana.concurrent.LockedOwnThread)
        - locked <0x000000076c6392f0> (a com.mirana.concurrent.LockedOwnThread)
    "Thread-0":
        at com.mirana.concurrent.LockedOwnThread$AThread.run(LockedOwnThread.java:27)
        - waiting to lock <0x000000076c636568> (a java.lang.Class for com.mirana.concurrent.LockedOwnThread)
        - locked <0x000000076c5806f8> (a java.lang.Class for java.lang.Object)
    
    Found 1 deadlock.
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    从输出信息中,可明显发觉两个线程彼此锁定了对方需要的锁(0x000000076c636568与0x000000076c5806f8)。

    在打印的堆栈信息中,我们还发现了如下信息:

    "Thread-0" #11 prio=5 os_prio=0 tid=0x000000001e902000 nid=0x5b34c waiting for monitor entry [0x000000001f5bf000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at com.mirana.concurrent.LockedOwnThread$AThread.run(LockedOwnThread.java:27)
        - waiting to lock <0x000000076c636538> (a java.lang.Class for com.mirana.concurrent.LockedOwnThread)
        - locked <0x000000076c5806f8> (a java.lang.Class for java.lang.Object)
    
       Locked ownable synchronizers:
        - None
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Locked ownable synchronizers是个什么东东?按照官方定义

    一个可持有的同步器多半是线程独有并且使用了AbstractOwnableSynchronizer(或是其子类)去实现它的同步特性,ReentrantLock与ReentrantReadWriteLock就是JAVA平台提供的两个例子。

    我们将程序改为如下形式,依旧为死锁形式:
    ```java
    static class AThread extends Thread {
    
        private ReentrantLock lock1;
    
        private ReentrantLock lock2;
    
        /**
         * @param lock1
         * @param lock2
         */
        public AThread(ReentrantLock lock1, ReentrantLock lock2) {
            super();
            this.lock1 = lock1;
            this.lock2 = lock2;
        }
    
    
    
        public void run() {
            try {
                lock1.lock();
                Thread.sleep(3000); 
                //  必须获取两个锁后才执行操作
                lock2.lock();
                System.out.println("A: I have all Locks!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock2.unlock();
                lock1.unlock();
            }
        }
    
    }
    
    static class BThread extends Thread {
    
        private ReentrantLock lock1;
    
        private ReentrantLock lock2;
    
        /**
         * @param lock1
         * @param lock2
         */
        public BThread(ReentrantLock lock1, ReentrantLock lock2) {
            super();
            this.lock1 = lock1;
            this.lock2 = lock2;
        }
    
    
    
        public void run() {
            try {
                lock2.lock();
                Thread.sleep(1000); 
                //  必须获取两个锁后才执行操作
                lock1.lock();
                System.out.println("B: I have all Locks!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock1.unlock();
                lock2.unlock();
            }
        }
    
    }
    
    //  测试程序主函数
    public static void main(String[] args) throws InterruptedException {
        final ReentrantLock lock1 = new ReentrantLock();
        final ReentrantLock lock2 = new ReentrantLock();
        new AThread(lock1, lock2).start();
        new BThread(lock1, lock2).start();
    }
    
    
    
    
    <div class="se-preview-section-delimiter"></div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    最后打印线程的堆栈信息,出现的内容如下:

    "Thread-1" #12 prio=5 os_prio=0 tid=0x000000001ef5a000 nid=0x1c2c waiting on condition [0x000000001fcbf000]
       java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x000000076c637ca0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
        at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
        at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
        at com.mirana.concurrent.LockedOwnThread$BThread.run(LockedOwnThread.java:70)
    
       Locked ownable synchronizers:
        - <0x000000076c637cd0> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    发现ReentrantLock与内置锁有如下3点不同: 
    1. 等待的对象不同,内置锁是“monitor entry”(监视器进入点),而ReentrantLock是“condition”(条件); 
    2. 线程的状态不同,内置锁是“BLOCKED”,而ReentrantLock是“WAITING”; 
    3. 锁定的同步器不同,内置锁没有,而ReentrantLock则指向持有的同步器;

    结论

    通过jstack可快速检查到死锁情况,并能给出冲突的锁与监测对象,另外,内置锁对象与ReentrantLock在运行中表现出截然不同的状态。

    原文地址:https://blog.csdn.net/yiifaa/article/details/76013837

  • 相关阅读:
    js对象排序
    路由懒加载优化
    RabbitMQ---1、安装与部署
    RabbitMQ入门教程系列
    c#项目代码风格要求
    C#RabbitMQ基础学习笔记
    C# 协变和逆变
    获取当前系统的基本信息
    html制作chm格式开源文档
    WPF: RenderTransform特效
  • 原文地址:https://www.cnblogs.com/draem0507/p/9302738.html
Copyright © 2011-2022 走看看