死锁

死锁(Deadlock)是并发系统中多个进程/线程因互相持有对方所需资源且不释放,导致全体永久阻塞、无法继续推进的状态。

四个必要条件(Coffman 条件)

必须同时满足才会死锁,破任一即可避免:

  1. 互斥:资源只能被一个占用(如锁、打印机)
  2. 占有且等待:持有一资源的同时等待另一资源
  3. 不可抢占:已分配资源不能被强行夺走,只能主动释放
  4. 循环等待:A等B、B等C、C等A,形成环

常见场景

  • 数据库:事务1锁表A等表B,事务2锁表B等表A
  • 多线程:线程1 lock(a); lock(b),线程2 lock(b); lock(a)
  • 分布式:两个服务互相 RPC 调用且都加了本地锁

处理方式对比

策略 做法 优缺点
预防 破坏四条件之一(如按固定顺序加锁、一次性申请所有资源) 简单,但可能降低并发度
避免 银行家算法,分配前判断是否会进入不安全状态 理论完美,实际难获取未来需求
检测+恢复 定期建资源分配图找环,发现后回滚/终止进程 允许死锁发生,开销在检测与恢复
忽略 假装不存在,重启解决(多数操作系统/业务系统的现实选择) 成本最低,适合死锁概率极低的场景

工程级避坑要点

  • 统一加锁顺序:所有地方都按 a → b → c 顺序拿锁,循环等待不成立
  • 加超时tryLock(timeout),拿不到就回退并释放已持锁
  • 减小锁粒度:用读写锁、分段锁,别长事务占着锁做 IO
  • 数据库层:短事务、避免用户交互中间留事务、FK 索引齐全防隐式锁升级
  • 工具:Java 用 jstackBLOCKED 链;MySQL 查 information_schema.INNODB_TRX + SHOW ENGINE INNODB STATUS
上一篇
下一篇