前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >死锁分析以及检测工具详解

死锁分析以及检测工具详解

作者头像
JAVA葵花宝典
发布2020-02-20 18:07:44
7120
发布2020-02-20 18:07:44
举报
文章被收录于专栏:JAVA葵花宝典JAVA葵花宝典

锁的状态

死锁:线程1等待线程2的互斥持有资源,而线程2等着线程1的互斥持有资源,两个线程都无法进行执行。

活锁:线程持续重试一个总是失败的操作,导致无法继续执行。(不是本文的重点)

饿死:线程一直被调度器延迟访问其赖以执行的资源,也许是调度器先于低优先级的线程而执行高优先级的线程,同时总是会有一个高优先级的线程可以执行,饿死也叫做无限延迟。

死锁的案例

代码如下所示:

代码语言:javascript
复制
package com.karl.concurrent.deadlock;

/**
 * 描述:  死锁的场景
 *
 * @author mh
 * @create 2020-02-11 15:43
 */
public class DeadLockTest {
    private Object object1 = new Object();
    private Object object2 = new Object();

    public static void main(String[] args) {
        DeadLockTest deadLockTest = new DeadLockTest();

        Runnable runnable1 = () -> {
            while (true) {
                deadLockTest.method01();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {

                }
            }
        };

        Thread thread01 = new Thread(runnable1, "thread01");

        Runnable runnable2 = () -> {
            while (true) {
                deadLockTest.method02();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {

                }
            }
        };
        Thread thread02 = new Thread(runnable2, "thread02");


        thread01.start();
        thread02.start();
    }


    public void method01() {
        synchronized (object1) {
            synchronized (object2) {
                System.out.println("method01 invoked");
            }

        }
    }


    public void method02() {
        synchronized (object2) {
            synchronized (object1) {
                System.out.println("method02 invoked");
            }
        }
    }

}

控制台:

根据图中我们可以看出,程序在运行中,但一直没有任何输出。

图解:

死锁的检测工具

java VisualVM

打开方式:jvisualvm命令即可

界面:

双击本地下的我们刚才执行的程序DeadLockTest,的到如下页面:

我们选择Dump线程

如图可知:

  • 线程01 02 在阻塞状态
  • 都在等待获取monitor持有权
  • 线程01 等待锁0x000000076ada8128,而且已经锁定了0x000000076ada8138。
  • 线程02 等待0x000000076ada8138,而且已经锁定了0x000000076ada8128。刚好和线程01 是相反的。

具体的细节大家可以在本地演示一下。

通过命令行工具检测死锁

jps -l 找到我们的程序id

代码语言:javascript
复制
95007 com.karl.concurrent.deadlock.DeadLockTest

jstack 95007 查看线程情况

代码语言:javascript
复制
2020-02-11 18:15:10
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.181-b13 mixed mode):

"Attach Listener" #14 daemon prio=9 os_prio=31 tid=0x00007ffe9308c000 nid=0xa603 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"DestroyJavaVM" #13 prio=5 os_prio=31 tid=0x00007ffe940a6800 nid=0xe03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"thread02" #12 prio=5 os_prio=31 tid=0x00007ffe940a5800 nid=0xa703 waiting for monitor entry [0x0000700002706000]
   java.lang.Thread.State: BLOCKED (on object monitor)
  at com.karl.concurrent.deadlock.DeadLockTest.method02(DeadLockTest.java:60)
  - waiting to lock <0x000000076aeefc20> (a java.lang.Object)
  - locked <0x000000076aeefc30> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$1(DeadLockTest.java:31)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$2/381259350.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)

"thread01" #11 prio=5 os_prio=31 tid=0x00007ffe940a5000 nid=0xa903 waiting for monitor entry [0x0000700002603000]
   java.lang.Thread.State: BLOCKED (on object monitor)
  at com.karl.concurrent.deadlock.DeadLockTest.method01(DeadLockTest.java:50)
  - waiting to lock <0x000000076aeefc30> (a java.lang.Object)
  - locked <0x000000076aeefc20> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$0(DeadLockTest.java:18)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$1/1607521710.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)

"Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007ffe94049000 nid=0x3e03 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x00007ffe95875000 nid=0x4003 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #8 daemon prio=9 os_prio=31 tid=0x00007ffe93053800 nid=0x3c03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #7 daemon prio=9 os_prio=31 tid=0x00007ffe93053000 nid=0x3b03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #6 daemon prio=9 os_prio=31 tid=0x00007ffe93052000 nid=0x3a03 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x00007ffe93050800 nid=0x3803 runnable [0x0000700001eee000]
   java.lang.Thread.State: RUNNABLE
  at java.net.SocketInputStream.socketRead0(Native Method)
  at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
  at java.net.SocketInputStream.read(SocketInputStream.java:171)
  at java.net.SocketInputStream.read(SocketInputStream.java:141)
  at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
  at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
  at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
  - locked <0x000000076ac83770> (a java.io.InputStreamReader)
  at java.io.InputStreamReader.read(InputStreamReader.java:184)
  at java.io.BufferedReader.fill(BufferedReader.java:161)
  at java.io.BufferedReader.readLine(BufferedReader.java:324)
  - locked <0x000000076ac83770> (a java.io.InputStreamReader)
  at java.io.BufferedReader.readLine(BufferedReader.java:389)
  at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007ffe9301d800 nid=0x3703 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007ffe9282a000 nid=0x4c03 in Object.wait() [0x0000700001be2000]
   java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x000000076ab08ed0> (a java.lang.ref.ReferenceQueue$Lock)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
  - locked <0x000000076ab08ed0> (a java.lang.ref.ReferenceQueue$Lock)
  at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
  at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)

"Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007ffe9300f800 nid=0x4d03 in Object.wait() [0x0000700001adf000]
   java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x000000076ab06bf8> (a java.lang.ref.Reference$Lock)
  at java.lang.Object.wait(Object.java:502)
  at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
  - locked <0x000000076ab06bf8> (a java.lang.ref.Reference$Lock)
  at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=31 tid=0x00007ffe9581c000 nid=0x4e03 runnable

"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007ffe92806000 nid=0x1d07 runnable

"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007ffe92807000 nid=0x1f03 runnable

"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007ffe92807800 nid=0x2203 runnable

"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007ffe9280b000 nid=0x2a03 runnable

"GC task thread#4 (ParallelGC)" os_prio=31 tid=0x00007ffe9280b800 nid=0x2b03 runnable

"GC task thread#5 (ParallelGC)" os_prio=31 tid=0x00007ffe9280c800 nid=0x5303 runnable

"GC task thread#6 (ParallelGC)" os_prio=31 tid=0x00007ffe9280d000 nid=0x5103 runnable

"GC task thread#7 (ParallelGC)" os_prio=31 tid=0x00007ffe9280d800 nid=0x2d03 runnable

"VM Periodic Task Thread" os_prio=31 tid=0x00007ffe9400a000 nid=0x5503 waiting on condition

JNI global references: 319


Found one Java-level deadlock:
=============================
"thread02":
  waiting to lock monitor 0x00007ffe92826cb8 (object 0x000000076aeefc20, a java.lang.Object),
  which is held by "thread01"
"thread01":
  waiting to lock monitor 0x00007ffe928282b8 (object 0x000000076aeefc30, a java.lang.Object),
  which is held by "thread02"

Java stack information for the threads listed above:
===================================================
"thread02":
  at com.karl.concurrent.deadlock.DeadLockTest.method02(DeadLockTest.java:60)
  - waiting to lock <0x000000076aeefc20> (a java.lang.Object)
  - locked <0x000000076aeefc30> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$1(DeadLockTest.java:31)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$2/381259350.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)
"thread01":
  at com.karl.concurrent.deadlock.DeadLockTest.method01(DeadLockTest.java:50)
  - waiting to lock <0x000000076aeefc30> (a java.lang.Object)
  - locked <0x000000076aeefc20> (a java.lang.Object)
  at com.karl.concurrent.deadlock.DeadLockTest.lambda$main$0(DeadLockTest.java:18)
  at com.karl.concurrent.deadlock.DeadLockTest$$Lambda$1/1607521710.run(Unknown Source)
  at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

也能查看到死锁的状况

总结

生产环境死锁的检测,通常都是通过命令行的方式进行查看。

作者:小鱼儿-karl

原文链接:https://blog.csdn.net/qq_33249725/article/details/104267428

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA葵花宝典 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
检测工具
域名服务检测工具(Detection Tools)提供了全面的智能化域名诊断,包括Whois、DNS生效等特性检测,同时提供SSL证书相关特性检测,保障您的域名和网站健康。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档