锁的状态
死锁:线程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