通过jdk工具jps、jstack排查死锁问题

java程序中出现死锁问题,如果不了解排查方法,是束手无策的,今天看一下如何使用工具来查看死锁

有如下代码:

 1 package com.test.thread;
 2 
 3 /**
 4  * 死锁
 5  */
 6 public class Demo4 {
 7     public static void main(String[] args) {
 8         User u1 = new User("u1");
 9         User u2 = new User("u2");
10         Thread t1 = new Thread(new SynAddRunnable(u1, u2,1,2,true));
11         Thread t2 = new Thread(new SynAddRunnable(u1, u2,2,1,false));
12         t1.setName("t1");
13         t2.setName("t2");
14         t1.start();
15         t2.start();
16     }
17 
18     static class SynAddRunnable implements Runnable {
19         User u1, u2;
20         int a,b;
21         boolean flag;
22 
23         public SynAddRunnable(User u1, User u2, int a, int b, boolean flag) {
24             this.u1 = u1;
25             this.u2 = u2;
26             this.a = a;
27             this.b = b;
28             this.flag = flag;
29         }
30 
31         @Override
32         public void run() {
33             try {
34                 if (flag) {
35                     synchronized (u1) {
36                         System.out.println("u1 lock");
37                         try {
38                             Thread.sleep(1000);
39                         } catch (InterruptedException e) {
40                             e.printStackTrace();
41                         }
42                         synchronized (u2) {
43                             System.out.println(a + b);
44                         }
45                     }
46                 } else {
47                     synchronized (u2) {
48                         System.out.println("u2 lock");
49                         try {
50                             Thread.sleep(1000);
51                         } catch (InterruptedException e) {
52                             e.printStackTrace();
53                         }
54                         synchronized (u1) {
55                             System.out.println(a + b);
56                         }
57                     }
58                 }
59             }catch (Exception e){
60                 e.printStackTrace();
61             }
62         }
63     }
64 
65     static class User{
66         private String name;
67 
68         public User(String name){
69             this.name = name;
70         }
71 
72         public void setName(String name){
73             this.name = name;
74         }
75 
76         public String getName(){
77             return this.name;
78         }
79 
80         @Override
81         public String toString() {
82             return "User{" +
83                     "name='" + name + '\'' +
84                     '}';
85         }
86     }
87 }

程序中:thread1持有u1的锁,thread2持有u2的锁,thread1等待获取u2的锁,thread2等待获取u1的锁,相互需要获取的锁都被对方持有者,造成了死锁。程序运行中一直无法结束。

 

通过jdk工具jps、jstack排查死锁问题

jps、jstack都是jdk提供的命令工具,方便用户排查程序的一些问题。更详细的用法见文档最后。

步骤一:使用jsp查找程序进行

jps:jdk提供的一个工具,可以查看到正在运行的java进程

PS E:\code> jps -l
19092 org.jetbrains.idea.maven.server.RemoteMavenServer36
7444 com.test.thread.Demo4
17352
1880 sun.tools.jps.Jps
18824 org.jetbrains.jps.cmdline.Launcher

 

步骤二:使用jstack查看线程堆栈信息

jstack:jdk提供的一个工具,可以查看java进程中线程堆栈信息。更详细的用法见文档最后。

PS E:\code> jstack 7444
2022-03-18 11:23:20
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode):

"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000002c5e800 nid=0x2f60 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"t2" #13 prio=5 os_prio=0 tid=0x000000001e3ae000 nid=0x3f14 waiting for monitor entry [0x000000002009f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.test.thread.Demo4$SynAddRunalbe.run(Demo4.java:55)
        - waiting to lock <0x000000076b68b060> (a com.test.thread.Demo4$User)
        - locked <0x000000076b68b0a0> (a com.test.thread.Demo4$User)
        at java.lang.Thread.run(Thread.java:748)

"t1" #12 prio=5 os_prio=0 tid=0x000000001e3ad000 nid=0x3e88 waiting for monitor entry [0x000000001ff9f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at com.test.thread.Demo4$SynAddRunalbe.run(Demo4.java:43)
        - waiting to lock <0x000000076b68b0a0> (a com.test.thread.Demo4$User)
        - locked <0x000000076b68b060> (a com.test.thread.Demo4$User)
        at java.lang.Thread.run(Thread.java:748)

"Service Thread" #11 daemon prio=9 os_prio=0 tid=0x000000001e34e000 nid=0x5960 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C1 CompilerThread3" #10 daemon prio=9 os_prio=2 tid=0x000000001e2aa800 nid=0x4a74 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x000000001e2a9800 nid=0x5004 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x000000001e2a8800 nid=0x36bc waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x000000001e292000 nid=0x41c0 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x000000001e29d000 nid=0x1bf8 runnable [0x000000001f89e000]
   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 <0x000000076b7d0720> (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 <0x000000076b7d0720> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:49)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001e24e000 nid=0x4830 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

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

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001e1e3800 nid=0x3634 in Object.wait() [0x000000001f53f000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076b508ec8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
        - locked <0x000000076b508ec8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

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

"VM Thread" os_prio=2 tid=0x000000001caf6800 nid=0x32ac runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002e07800 nid=0x55a0 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002e09000 nid=0x3244 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002e0a800 nid=0x2528 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002e0c000 nid=0x2598 runnable

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000002e0e800 nid=0x5be0 runnable

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002e10800 nid=0x3294 runnable

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002e13800 nid=0x22b0 runnable

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002e15000 nid=0x8b4 runnable

"GC task thread#8 (ParallelGC)" os_prio=0 tid=0x0000000002e16000 nid=0x5334 runnable

"GC task thread#9 (ParallelGC)" os_prio=0 tid=0x0000000002e17000 nid=0x5bd0 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x000000001e3a8000 nid=0x521c waiting on condition

JNI global references: 16


Found one Java-level deadlock:
=============================
"t2":
  waiting to lock monitor 0x000000001cb00be8 (object 0x000000076b68b060, a com.test.thread.Demo4$User),
  which is held by "t1"
"t1":
  waiting to lock monitor 0x000000001cb03528 (object 0x000000076b68b0a0, a com.test.thread.Demo4$User),
  which is held by "t2"

Java stack information for the threads listed above:
===================================================
"t2":
        at com.test.thread.Demo4$SynAddRunalbe.run(Demo4.java:55)
        - waiting to lock <0x000000076b68b060> (a com.test.thread.Demo4$User)
        - locked <0x000000076b68b0a0> (a com.test.thread.Demo4$User)
        at java.lang.Thread.run(Thread.java:748)
"t1":
        at com.test.thread.Demo4$SynAddRunalbe.run(Demo4.java:43)
        - waiting to lock <0x000000076b68b0a0> (a com.test.thread.Demo4$User)
        - locked <0x000000076b68b060> (a com.test.thread.Demo4$User)
        at java.lang.Thread.run(Thread.java:748)

Found 1 deadlock.

关注如下两个部分:

 

 

可以死锁的代码是在Demo4.java的49行和42行,此时我们就可以去优化代码,解决死锁问题。

 

 

ps:参考深入理解java虚拟机系列

posted @ 2022-03-18 11:43  r1-12king  阅读(427)  评论(0编辑  收藏  举报