面试知识库
进阶

死锁与处理策略#

一句话答案#

死锁四必要条件:互斥/占有等待/不可剥夺/循环等待,预防方式:破坏其中一个条件(如超时释放/按序申请)。

核心要点

预防:

  • 破坏占有等待:一次性申请所有资源
  • 破坏不可剥夺:超时释放
  • 破坏循环等待:资源排序,按序申请

检测: 资源分配图 / jstack 线程 dump / SHOW ENGINE INNODB STATUS

面试回答(2分钟版)

死锁是指两个或多个进程互相持有对方所需的资源并等待对方释放,导致所有相关进程永久阻塞。死锁的产生需要同时满足四个必要条件:互斥即资源同一时刻只能被一个进程使用、占有等待即进程持有资源的同时等待其他资源、不可剥夺即已分配的资源不能被强制收回、循环等待即存在进程间的环形等待链。预防死锁的思路就是破坏其中至少一个条件:破坏占有等待可以要求进程一次性申请所有需要的资源;破坏不可剥夺可以设置超时机制获取不到就释放已持有的资源,比如 Java 的 tryLock 带超时;破坏循环等待可以对资源编号按固定顺序申请,保证不会形成环路。死锁检测方面,Java 中可以用 jstack 打印线程转储查看 BLOCKED 状态的线程和锁等待关系,JMX 的 ThreadMXBean 也能编程检测死锁。MySQL 的 InnoDB 引擎内置了死锁检测机制,通过 SHOW ENGINE INNODB STATUS 可以查看最近的死锁信息,InnoDB 会自动选择代价小的事务回滚来打破死锁。

追问与易错

追问方向:

  • “怎么检测 Java 死锁?”→ jstack 打印线程转储看 BLOCKED 状态和锁等待链、JMX 的 ThreadMXBean.findDeadlockedThreads() 编程检测、jconsole 图形化查看
  • “数据库死锁和 Java 死锁排查区别?”→ Java 死锁靠 jstack 看线程;MySQL InnoDB 内置死锁检测自动回滚代价小的事务,用 SHOW ENGINE INNODB STATUS 查看死锁日志
  • “哲学家就餐问题怎么解决?”→ 破坏循环等待:给筷子编号按序申请、限制同时进餐人数(信号量)、引入服务员统一分配资源(资源分配器模式)

易错点:

  • ❌ 避免所有嵌套锁就不会死锁——顺序不一致也会
  • ❌ 死锁只影响两个线程——可能是多线程循环等待