通过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行,此时我们就可以去优化代码,解决死锁问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构