死锁示例

这次记录一个线程死锁的例子。直接上代码:

 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工具,线程页签界面上鲜明地展示,当前应用存在死锁。 deak lock

点击右上角线程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.