死锁
死锁:多个进程互相等待对方持有的资源,谁也走不动。面试主线:四条件、三类解法、银行家算法。
死锁四条件
四个条件同时满足才死锁:
四条件缺一不可
| 条件 | 含义 |
|---|---|
| 互斥 | 资源一次只能一个进程用 |
| 持有并等待 | 进程持有一个资源还等另一个 |
| 不可剥夺 | 资源不能被强制拿走 |
| 循环等待 | 等待链成环 |
面试话术:破坏任意一个条件就能防死锁,四个条件要能背、能解释。
三类解法
| 策略 | 做法 | 代价 |
|---|---|---|
| 预防(破坏条件) | 一次性申请所有资源(破持有等待)、按序申请(破循环等待)、可剥夺 | 资源利用率低 |
| 避免(动态判断) | 银行家算法:分配前判断是否安全 | 需要预知最大需求 |
| 检测与恢复 | 允许死锁,检测到就回滚/杀进程 | 恢复代价不可控 |
- 预防:按固定顺序申请资源是工程最常用(如先锁 A 再锁 B,全项目统一顺序)
- 避免:银行家算法是理论重点,工程少用(预知需求不现实)
- 检测:等待图(wait-for graph)有环即死锁;恢复:终止进程或资源抢占
银行家算法
安全状态判断:分配资源后,是否存在一个进程执行序列,让每个进程都能依次完成(拿到所需资源)。
available: 系统剩余资源
need[i]: 进程 i 还需资源
每次分配前模拟: 找一个 need ≤ available 的进程,
假设它完成并归还, 重复, 直到所有进程完成 → 安全, 才分配要点:分配前检查安全性,不安全就不分配(宁可等待)。答出“模拟执行序列判断安全”就够。
工程实践
- 数据库死锁:事务互等锁(见数据库锁篇),靠超时和死锁检测回滚
- 分布式锁死锁:锁过期 + 看门狗(见 Redis 分布式锁篇)
- 编码规范:锁顺序一致、锁粒度小、加锁超时
面试追问
- 死锁四条件? 互斥、持有并等待、不可剥夺、循环等待。同时满足才死锁
- 怎么预防死锁? 破坏四条件之一:一次申请全部资源、固定顺序申请、允许剥夺
- 银行家算法干什么? 分配前判断系统是否仍安全(存在完成序列)。不安全不分配
- 怎么检测死锁? 等待图有环。检测到后终止进程或回滚
- 工程上怎么避免? 统一锁顺序(破循环等待)、锁超时、小锁粒度。数据库和分布式锁各有机制