用jstack排查java死锁的核心是“抓现场→看输出→找循环”:先用jps -l查pid,再用jstack -f -l pid > dump.txt导出带锁详情的线程快照;接着在dump.txt末尾搜索found one java-level deadlock,分析waiting to lock和which is held by确定阻塞链;然后回溯各线程堆栈定位synchronized或lock.lock()代码行,比对锁对象hashcode,检查加锁顺序是否不一致;最后可通过连续两次jstack对比blocked线程堆栈是否固定来验证。

用 jstack 排查 Java 多线程死锁,核心是“抓现场→看输出→找循环”,不依赖猜测,靠工具直接暴露阻塞链。
第一步:快速获取进程 ID 和线程快照
先确认目标 Java 进程的 PID:
- 执行 jps -l,找到你的应用类名对应的数字(比如 12345 com.example.MyApp)
- 用 jstack -l 12345 > dump.txt 导出带锁详情的线程快照
(-l 很关键,它会显示谁持有哪把锁、谁在等哪把锁) - 若进程已卡死无响应,可加 -F 强制抓取:jstack -F -l 12345 > dump.txt
第二步:定位死锁摘要和线程关系
打开 dump.txt,直接拉到文件末尾搜索关键词:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 查找 Found one Java-level deadlock: —— 如果存在,jstack 会自动标出全部死锁线程
- 下面会列出类似结构:
"Thread-1": waiting to lock (a java.lang.Object), which is held by "Thread-0"
"Thread-0": waiting to lock (a java.lang.Object), which is held by "Thread-1" - 注意两个关键字段:
waiting to lock → 当前线程想拿但拿不到的锁
locked 或 which is held by → 它自己拿着的锁,正被另一个线程等着
第三步:回溯代码定位根因
光知道“谁等谁”还不够,得找到具体哪段代码在加锁:
- 在 dump.txt 中找到对应线程的完整堆栈(比如 "Thread-0" 的 Java stack information 部分)
- 看最后一行或倒数几行的 at xxx.xxx.method(XXX.java:23),定位到 synchronized 块或 Lock.lock() 调用位置
- 重点比对多个死锁线程持有的锁对象 identity hashcode(如 ),在代码里搜这些锁的声明位置
- 检查是否出现加锁顺序不一致:例如一个方法先锁 A 再锁 B,另一个却先锁 B 再锁 A
第四步:验证与辅助技巧
单次 dump 有时不够,可结合以下方式增强判断:
- 连续执行两次 jstack(间隔 2–3 秒),对比 BLOCKED 线程的堆栈是否始终停在同一个 synchronized 或 lock() 调用上
- 关注线程状态为 BLOCKED 且堆栈中含 waiting to lock 的条目,它们大概率是死锁参与者
- 若用的是 Collections.synchronizedMap 等包装类,注意它的锁就是 map 实例本身,避免外部再用 synchronized(map) 造成重复竞争
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










