【多线程】定位线程死锁
定位线程死锁的方式
- jstack pid
- 使用arthas
写一个死锁的小例子
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class DeadLockDemo { static Object o1 = new Object(); static Object o2 = new Object(); static ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 120, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100)); static CountDownLatch countDownLatch = new CountDownLatch(2); public static void main(String[] args) throws InterruptedException { executor.execute(() -> { synchronized (o1) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } synchronized (o2) { System.out.println("线程1获得了两把锁"); } countDownLatch.countDown(); } }); executor.execute(() -> { synchronized (o2) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } synchronized (o1) { System.out.println("线程2获得了两把锁"); } countDownLatch.countDown(); } }); countDownLatch.await(); } }
这个demo 启动后,线程就会死锁掉,
那怎样去查看是哪里发生了死锁呢?
方法一 jstack (推荐)
直接 jps 看一下要定位的进程的 Pid
然后 jstack pid > deadlock.log 打栈信息输出到一个文本中(当然,不输出也是可以的,个人喜欢)
然后在栈的后面,可以看到这么一段信息:
Java stack information for the threads listed above: =================================================== "pool-1-thread-2": at com.carrot.thread.deadlock.DeadLockDemo.lambda$main$1(DeadLockDemo.java:50) - waiting to lock <0x000000076ac30978> (a java.lang.Object) - locked <0x000000076ac30988> (a java.lang.Object) at com.carrot.thread.deadlock.DeadLockDemo$$Lambda$2/1595428806.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) "pool-1-thread-1": at com.carrot.thread.deadlock.DeadLockDemo.lambda$main$0(DeadLockDemo.java:36) - waiting to lock <0x000000076ac30988> (a java.lang.Object) - locked <0x000000076ac30978> (a java.lang.Object) at com.carrot.thread.deadlock.DeadLockDemo$$Lambda$1/1329552164.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Found 1 deadlock.
这里就很清楚地看到是哪些线程发生了死锁了。。。(当然这个是造的例子,定位起来也比较简单,具体情况以真实案例为准吧)
嗯...
方法二 使用arthas
这个就没什么好说的了, 进入 arthas 后
使用 thread -b
不过这个信息偏少,虽然也够了
[arthas@761]$ thread -b "pool-1-thread-2" Id=12 BLOCKED on java.lang.Object@1c01e8b4 owned by "pool-1-thread-1" Id=11 at com.carrot.thread.deadlock.DeadLockDemo.lambda$main$1(DeadLockDemo.java:53) - blocked on java.lang.Object@1c01e8b4 - locked java.lang.Object@7bf02312 <---- but blocks 1 other threads! at com.carrot.thread.deadlock.DeadLockDemo$$Lambda$2/1595428806.run(Unknown Source) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Number of locked synchronizers = 1 - java.util.concurrent.ThreadPoolExecutor$Worker@3feba861
嗯,后续再补充吧。
分类:
java
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南