最直接有效的方式是用Arthas执行thread -d命令秒级检测死锁;若发现“Found 1 deadlock”,再通过thread 查看各线程持有的锁(locked)和等待的锁(waiting to lock),比对锁地址定位循环等待关系,并结合sc、sm、trace等命令追溯到具体业务代码。

Java 生产环境出现死锁,最直接有效的方式是用 Arthas 实时诊断 —— 它无需重启、不侵入代码、支持线上秒级定位。核心思路是:先确认是否真死锁,再看哪些线程卡住、持有哪些锁、等待哪个锁、由哪段代码触发。
一、快速检测是否存在死锁
连接 Arthas 后,执行命令:
thread -d
该命令会列出所有处于 BLOCKED 状态的线程,并自动标出死锁链。如果存在死锁,Arthas 会明确打印 “Found 1 deadlock.” 并给出参与死锁的线程 ID 和锁信息。这是最快一步验证手段,比 jstack 手动分析高效得多。
二、定位具体阻塞线程和锁持有关系
若 thread -d 已发现死锁,进一步查看关键线程详情:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 用 thread
查看指定线程的完整堆栈(含锁状态) - 重点关注堆栈中带
waiting to lock和locked的行 —— 前者是它在等什么锁,后者是它自己已持有的锁 - 对比多个死锁线程的锁地址(如
0x0000000712345678),能清晰看出 A 持有锁 L1 等 L2,B 持有锁 L2 等 L1
三、追溯锁对象来源与业务代码
仅知道锁地址还不够,要定位到哪行代码创建/竞争这个锁:
- 执行 sc -d *ClassName* 查找相关类是否被加载(缩小范围)
- 用 sm ClassName methodName 查看方法字节码,确认是否用了 synchronized 或 ReentrantLock
- 结合 thread -n 5 查看 CPU 占用最高的前 5 个线程,有时死锁虽未爆发,但线程长期 BLOCKED 已导致响应变慢
- 若锁是
ReentrantLock,可用 ognl 命令尝试获取其内部 state、queue 等字段(需注意 OGNL 表达式安全限制)
四、辅助技巧:实时监控锁竞争热点
预防胜于排查,可在线上持续观察锁争用情况:
- trace -j ClassName methodName 追踪方法调用耗时,特别关注含 synchronized 或 lock() 的方法是否频繁超时
- watch ClassName methodName '{params,returnObj}' -x 3 -n 5 观察参数和返回值,辅助判断是否因特定数据引发锁顺序不一致
- 配合 dashboard 命令看整体线程状态趋势,BLOCKED 线程数突增往往是死锁前兆
Arthas 排查死锁的本质,是把 JVM 的线程快照能力交互化、语义化。只要连接成功,30 秒内就能完成从现象确认到代码定位的闭环。关键是别只看堆栈,要对照锁地址、线程状态、业务逻辑三者交叉验证。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










