温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java如何定位死锁

发布时间:2021-09-06 17:33:57 来源:亿速云 阅读:178 作者:小新 栏目:开发技术

这篇文章将为大家详细讲解有关java如何定位死锁,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

    死锁

    死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。

    死锁发生的原因

    死锁的发生是由于资源竞争导致的,导致死锁的原因如下:

    • 系统资源不足,如果系统资源充足,死锁出现的可能性就很低。

    • 进程(线程)运行推进的顺序不合适。

    • 资源分配不当等。

    死锁发生的条件

    死锁的发生的四个必要条件:

    1. 互斥条件:一个资源每次只能被一个进程使用。

    2. 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

    3. 不可强行占有:进程(线程)已获得的资源,在未使用完之前,不能强行剥夺。

    4. 循环等待条件:若干进程(线程)之间形成一种头尾相接的循环等待资源关系。

    这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

    1:通过jstack定位死锁信息

    1.1:编写死锁代码

    Lock lock1 = new ReentrantLock();
      Lock lock2 = new ReentrantLock();
      
      ExecutorService exectuorService = Executors.newFixedThreadPool(2);
      
      exectuorService.submit(() -> {
         lock1.lock();
         try{
             Thread.sleep(1000);
         }catch(Exception e){}
         try{}
         finally{
           lock1.unlock();
           lock2.unlock();
         }
      });
      exectuorService.submit(() -> {
         lock2.lock();
         try{
            Thread.sleep(1000);
         }catch(Exception e){}
         
         try{}
         finally{
             lock1.unlock();
             lock2.unlock();
         }
      });

    1.2:查看死锁线程的pid

    • jps查看死锁的线程pid

    • 使用 jstack -l pid 查看死锁信息

    • 通过打印信息我们可以找到发生死锁的代码是在哪个位置

    "DestroyJavaVM" #13 prio=5 os_prio=31 tid=0x00007f9a1d8fe800 nid=0xd03 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
     - None
    
    "pool-1-thread-2" #12 prio=5 os_prio=31 tid=0x00007f9a1d8fe000 nid=0xa703 waiting on condition [0x000070000ff8e000]
       java.lang.Thread.State: WAITING (parking)
     at sun.misc.Unsafe.park(Native Method)
     - parking to wait for  <0x0000000795768cd8> (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.coco.util.SlideTimeUnit.lambda$main$1(SlideTimeUnit.java:63)
     at com.coco.util.SlideTimeUnit$$Lambda$2/565760380.run(Unknown Source)
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
     at java.lang.Thread.run(Thread.java:748)
    
       Locked ownable synchronizers:
     - <0x0000000795768d08> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
     - <0x0000000795a9e4e0> (a java.util.concurrent.ThreadPoolExecutor$Worker)
    
    "pool-1-thread-1" #11 prio=5 os_prio=31 tid=0x00007f9a2082c800 nid=0xa803 waiting on condition [0x000070000fe8b000]
       java.lang.Thread.State: WAITING (parking)
     at sun.misc.Unsafe.park(Native Method)
     - parking to wait for  <0x0000000795768d08> (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.coco.util.SlideTimeUnit.lambda$main$0(SlideTimeUnit.java:49)
     at com.coco.util.SlideTimeUnit$$Lambda$1/596512129.run(Unknown Source)
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
     at java.lang.Thread.run(Thread.java:748)
    
       Locked ownable synchronizers:
     - <0x0000000795768cd8> (a java.util.concurrent.locks.ReentrantLock$NonfairSync)
     - <0x0000000795a9ba28> (a java.util.concurrent.ThreadPoolExecutor$Worker)
    
    "Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007f9a2082c000 nid=0x4103 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
       Locked ownable synchronizers:
     - None
    
    "C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x00007f9a1e021800 nid=0x3f03 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE

    2:通过Arthas工具定位死锁

    2.1: 下载好Arthas的jar,然后运行

    有一个 thread -b 就可以查看到死锁信息

    [arthas@4182]$ thread -b
    "pool-1-thread-2" Id=12 WAITING on java.util.concurrent.locks.ReentrantLock$NonfairSync@2cb8a9a3 owned by "pool-1-thread-1" Id=11
        at sun.misc.Unsafe.park(Native Method)
        -  waiting on java.util.concurrent.locks.ReentrantLock$NonfairSync@2cb8a9a3
        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.coco.util.SlideTimeUnit.lambda$main$1(SlideTimeUnit.java:63)
        at com.coco.util.SlideTimeUnit$$Lambda$2/565760380.run(Unknown Source)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
    
        Number of locked synchronizers = 2
        - java.util.concurrent.ThreadPoolExecutor$Worker@6433a2
        - java.util.concurrent.locks.ReentrantLock$NonfairSync@3a855d13 <---- but blocks 1 other threads!

    3. 通过 Jvisualvm 定位死锁

    Jvisualvm 是一种自带的可视化工具,往往在在本地执行。

    通过 Jvisualvm 命令打开软件,选中进程,进入线程视图,会给出死锁提示:

    java如何定位死锁

    死锁的预防

    • 尽量避免使用多个锁,并且只有需要时才持有锁。

    • 如果使用多个锁,一定要设计好锁的获取顺序。

    • 使用带有超时的方法,为程序带来更多的可控性,比如指定获取锁的时间最多为5秒,超时就放弃。

    • 通过一些代码静态检查工具发现可能存在的死锁问题,比如FindBugs。

    关于“java如何定位死锁”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI