死锁判断需聚焦线程状态行、java.lang.Thread.State段和Locked ownable synchronizers块:先查BLOCKED线程的locked地址,再搜该地址是否被其他线程waiting to lock,若形成闭环即为死锁;ReentrantLock需通过Locked ownable synchronizers中owner thread确认持有者。

看堆栈日志判断线程持有哪些锁,关键不是通读全部内容,而是聚焦三处结构化信息:线程状态行、java.lang.Thread.State段、以及Locked ownable synchronizers块。
盯住线程状态和锁地址匹配
每个线程块开头类似这样:
"Thread-0" #12 prio=5 ... nid=0x3a5b waiting on condition [0x00007f8b3d9f9000]
往下找这一行:
立即学习“Java免费学习笔记(深入)”;
java.lang.Thread.State: BLOCKED (on object monitor)
紧跟着通常有一句:
- waiting to lock (a java.lang.Object)
这表示它正卡在 synchronized 块外,等着获取地址为 的对象锁。再往上看,找到同一段里另一句:
- locked (a java.lang.Object)
说明该线程自己已持有地址为 的锁。两个十六进制地址是否在不同线程间交叉出现(比如 A 等 B 持有的地址,B 又等 A 持有的地址),就是死锁链的直接证据。
区分 synchronized 和 ReentrantLock 的持有方式
synchronized 锁体现在 locked 和 waiting to lock 字样后;而 ReentrantLock 类型的锁不会出现在 monitor 行里,要查下面这个区域:
- 找到 Locked ownable synchronizers: 标题
- 其下若出现类似:
- (a java.util.concurrent.locks.ReentrantLock$NonfairSync) - 注意它后面是否带 owner thread: Thread-1 —— 这才是当前持锁者,不是看 monitor 地址
警惕非死锁阻塞,避免误判
以下情况 不构成死锁,jstack 日志里常见但别当成线索:
- parking to wait for :这是 AQS 队列中等待,属于正常同步器行为,不等于循环等待
- in Object.wait() 或 waiting on condition:线程在条件变量上挂起,未涉及锁竞争
- TIMED_WAITING (sleeping):只是休眠,与锁无关
快速定位技巧:用关键词分层扫描
导出 thread_dump.txt 后,可按顺序 grep 加速分析:
- 先搜 Found one Java-level deadlock —— 有就直接看结论部分
- 没有?再搜 BLOCKED (on object monitor),挑出所有被阻塞的线程
- 对每个 BLOCKED 线程,向上翻找它的 locked 行,记下地址
- 再搜这些地址,看谁在 waiting to lock —— 形成闭环即确认死锁


















