【多线程】定位线程死锁

定位线程死锁的方式

  • 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

嗯,后续再补充吧。

posted @   aaacarrot  阅读(399)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示