死锁排查需体现理解、实操与预防三层能力:先讲清互斥、占有并等待、不可抢占、循环等待四条件对应代码行为;再按jstack/Arthas/容器环境顺序说明线上定位步骤;最后用统一加锁顺序和tryLock超时给出可落地预防方案。

回答死锁排查类面试题,关键不是背定义,而是展现“理解+实操+预防”三层能力。面试官想确认你真在线上处理过问题,而不是只看过教程。
说清死锁的四个必要条件
别只说“互相等待”,要对应到代码行为:
- 互斥:synchronized 或 ReentrantLock 锁住的对象,同一时间只能被一个线程进入
- 占有并等待:Thread-1 拿着 lockA,又去 try lockB;Thread-2 拿着 lockB,又去 try lockA
- 不可抢占:Java 中没有机制能强制让 Thread-1 放开 lockA,只能等它自己退出同步块
- 循环等待:Thread-1 → 等 lockB(被 Thread-2 持有),Thread-2 → 等 lockA(被 Thread-1 持有),形成闭环
展示真实排查路径
线上出问题,不能靠猜。按顺序说明你怎么做:
- 用 jstack -l
抓取线程快照,重点看 “Found one Java-level deadlock” 和 “waiting to lock monitor” 的段落 - 结合业务日志,定位卡住的接口或定时任务,缩小可疑线程范围
- 用 Arthas thread -b 快速扫描当前阻塞在锁上的线程(比 jstack 更轻量、支持动态分析)
- 如果是容器环境,先 kubectl exec -it
-- jstack -l 1 ,避免连错机器
给出可落地的预防方案
光会查不够,面试官更想看你日常怎么防。挑两个最常用、最容易讲清楚的说:
- 统一加锁顺序:比如转账场景,约定所有操作都按 account.id 升序加锁——先锁小 ID,再锁大 ID,打破循环等待
- 用 tryLock + 超时:ReentrantLock.tryLock(3, TimeUnit.SECONDS),失败就释放已持锁并重试/降级,不硬等
- 补充一点加分项:在关键服务启动时,用 JMX 或 Actuator endpoint 暴露锁持有统计,配合监控告警
真正通关的回答,是把“为什么卡住→怎么找到卡点→以后怎么不卡”串成一条线,语气沉稳、细节扎实,不绕弯子。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











