用jstack -l定位死锁并修复:先抓快照确认死锁,再解析线程锁依赖关系,最后分层修复(紧急止血、代码优化、防御监控),并集成自动化检测。

直接用 jstack + 线程栈分析 定位死锁,比空讲理论强十倍——面试官要的是你“真干过、真查过、真解决过”的证据。
一、先快速复现并确认死锁存在
别一上来就翻源码。告诉面试官你会:
- 用 jstack -l
抓取带锁信息的线程快照(-l 是关键,否则看不到 LockInfo) - 在输出中搜索 "Found 1 deadlock" ——JVM 自带检测,优先信任它
- 如果没搜到,但业务明显卡住,会结合 jstat -gc
排除 GC 导致的假死,再用 jstack -e (JDK 11+)看更详细的锁等待链
二、精准读懂 jstack 输出的死锁现场
光看到“Found deadlock”不够,得讲出谁锁了谁、为什么等不到。比如这段典型输出:
Java stack information for the threads listed above:
===================================================
"Thread-A":
at com.example.DeadLockDemo$1.run(DeadLockDemo.java:15)
- waiting to lock <0x000000076b9a8a00> (a java.lang.Object)
- locked <0x000000076b9a8a10> (a java.lang.Object)
"Thread-B":
at com.example.DeadLockDemo$2.run(DeadLockDemo.java:25)
- waiting to lock <0x000000076b9a8a10> (a java.lang.Object)
- locked <0x000000076b9a8a00> (a java.lang.Object)
你要立刻指出:
→ Thread-A 持有 0x...8a10,想抢 0x...8a00;
→ Thread-B 持有 0x...8a00,想抢 0x...8a10;
→ 两个对象都是 new Object() 创建的普通锁,没有超时、不可中断,必然死锁。
三、不只定位,还要给出可落地的修复方案
面试官最怕“知道问题但改不动”。你可以分层说:
立即学习“Java免费学习笔记(深入)”;
-
紧急止血:用 jcmd
VM.native_memory summary 查内存是否被锁对象长期占用;必要时 kill -3 让应用自愈(仅限测试环境) - 代码级修复:统一加锁顺序(如按对象 hashCode 排序)、用 tryLock(timeout) 替代 synchronized、或改用 ReentrantLock#lockInterruptibly()
- 防御性设计:在关键锁操作前打日志(如 “acquiring lock on user-123”),配合 APM 工具(Arthas watch 命令)做线上锁行为监控
四、顺手展示你的工程意识
补一句让面试官眼前一亮的话:
“我们组把 jstack -l 加上自动解析脚本,集成进 CI 流水线——单元测试跑完自动检查线程状态,一旦发现 BLOCKED 超过 3 秒就失败。不是等上线才查死锁,是写代码时就拦住。”


















