面试知识库
进阶

死锁条件与排查#

一句话答案#

死锁四必要条件:互斥/占有等待/不可剥夺/循环等待;排查用 jstack/jconsole/Arthas thread -b。

核心要点

排查: jstack → 搜索 deadlock / jconsole 线程面板 / Arthas thread -b

预防: 保持加锁顺序一致 / tryLock超时 / 减小锁粒度 / 避免嵌套锁

面试回答(2分钟版)

死锁是两个或多个线程互相持有对方需要的锁而无限等待的状态,发生死锁需要同时满足四个必要条件:互斥、占有并等待、不可剥夺、循环等待。预防死锁的核心思路就是打破其中任一条件,最常用的方法有三种:第一是保持加锁顺序一致,所有线程按相同顺序获取锁就不会形成环路;第二是使用 ReentrantLock 的 tryLock 设置超时时间,拿不到就放弃已持有的锁重试;第三是减小锁粒度,避免嵌套加锁。排查线上死锁最直接的方式是 jstack 导出线程堆栈然后搜索 deadlock 关键字,JVM 会自动检测并报告死锁链路,也可以用 jconsole 的线程面板或 Arthas 的 thread -b 命令实时检测。实际工作中我会在代码规范里要求统一加锁顺序,配合 tryLock 超时机制做兜底。

追问与易错

追问方向:

  • “怎么预防死锁?”→ 统一加锁顺序打破循环等待、tryLock 超时打破占有等待、减小锁粒度减少嵌套锁、使用并发工具类替代手动加锁
  • “数据库死锁和 Java 死锁排查方式的区别?”→ Java 用 jstack 搜 deadlock 关键字或 Arthas thread -b;数据库用 SHOW ENGINE INNODB STATUS 查看死锁日志,MySQL 会自动检测并回滚代价小的事务
  • “你遇到过实际的死锁吗?”→ 这是经验题,建议准备一个真实案例:如两个服务互相调用对方持锁资源、或数据库事务交叉更新行锁,说清排查过程和解决方案

易错点:

  • ❌ 避免嵌套锁就不会死锁——顺序不一致也会
  • ❌ 用 tryLock 就一定不死锁——需设合理超时