死锁示例
这次记录一个线程死锁的例子。直接上代码:
1package test.heap;
2
3public class TestDeadLock {
4 public static void main(String[] args) throws InterruptedException {
5 new Thread(() -> A.testA(), "first thread").start();
6 new Thread(() -> B.testB(), "second thread").start();
7 Thread.sleep(120000);
8 System.out.println("main method end!");
9 }
10
11}
12
13class A {
14 public static synchronized void testA() {
15 System.out.println("A.methodA() invoked!");
16
17 try {
18 Thread.sleep(5000);
19 B.testB();
20 } catch (InterruptedException e) {
21 e.printStackTrace();
22 }
23 }
24}
25
26class B {
27 static synchronized void testB() {
28 System.out.println("B.methodB() invoked!");
29 try {
30 Thread.sleep(5000);
31 A.testA();
32 } catch (InterruptedException e) {
33 e.printStackTrace();
34 }
35 }
36}
在这个例子中,对于类A的同步方法testA(),当线程执行该方法时,需要首先获取类A的Class对象锁,睡眠5秒之后调用类B的静态同步方法testB()时,需要获取类B的Class对象锁。类B的testB方法和testA方法的逻辑一样。
显然,first thread线程执行testA方法时,获取了A的Class对象锁,睡眠5秒后尝试获取B的Clas对象锁,而second thread执行testB方法时,获取了B的Class对象锁,所以线程first thread睡醒之后获取不到A的Class对象锁,处于Block状态,同样地,该线程睡醒之后也获取不到A的Class对象锁,这两个线程相互永远等待,处于dead block状态!
VisualVM工具排查
打开Java VisualVM工具,线程页签界面上鲜明地展示,当前应用存在死锁。
点击右上角线程Dump按钮,进去之后可以看到所有线程的执行状态快照,拖到页面的最后面,会打印出死锁线程的相关信息。
1Found one Java-level deadlock:
2=============================
3"second thread":
4 waiting to lock monitor 0x14f48bbc (object 0x09fa2db8, a java.lang.Class),
5 which is held by "first thread"
6"first thread":
7 waiting to lock monitor 0x14f48adc (object 0x09fa2d60, a java.lang.Class),
8 which is held by "second thread"
9
10Java stack information for the threads listed above:
11===================================================
12"second thread":
13 at test.heap.A.testA(TestDeadLock.java:15)
14 - waiting to lock <0x09fa2db8> (a java.lang.Class for test.heap.A)
15 at test.heap.B.testB(TestDeadLock.java:31)
16 - locked <0x09fa2d60> (a java.lang.Class for test.heap.B)
17 at test.heap.TestDeadLock.lambda$main$1(TestDeadLock.java:6)
18 at test.heap.TestDeadLock$$Lambda$2/19993396.run(Unknown Source)
19 at java.lang.Thread.run(Thread.java:748)
20"first thread":
21 at test.heap.B.testB(TestDeadLock.java:28)
22 - waiting to lock <0x09fa2d60> (a java.lang.Class for test.heap.B)
23 at test.heap.A.testA(TestDeadLock.java:19)
24 - locked <0x09fa2db8> (a java.lang.Class for test.heap.A)
25 at test.heap.TestDeadLock.lambda$main$0(TestDeadLock.java:5)
26 at test.heap.TestDeadLock$$Lambda$1/17290025.run(Unknown Source)
27 at java.lang.Thread.run(Thread.java:748)
28
29Found 1 deadlock.