参考:死锁条件、处理策略与银行家算法速查
基于通用操作系统概念 · 核于 2026-08
速查
- 死锁定义:一组进程互相等待对方资源,永久阻塞、谁也前进不了。
- 四必要条件:互斥、占有并等待、不剥夺、循环等待——全满足才死锁,破坏其一即预防。
- 资源分配图(RAG):进程→资源(请求)、资源→进程(分配)。单实例资源有环⇔死锁;多实例需图化简。
- 四种处理策略:预防(破坏条件)、避免(银行家算法)、检测恢复(允许发生再处理)、鸵鸟(忽略)。
- 安全状态:存在安全序列(能依次完成的进程序列);安全一定不死锁,不安全只是有风险。
- 银行家算法:分配前先试探,再跑安全性算法判断是否仍安全,安全才真分配。
- 鸵鸟策略:Linux/Windows 实际做法——忽略死锁,由应用开发者自行避免。
- 饥饿:长期得不到资源但能调度;活锁:进程在动但无进展;都不等于死锁。
一、死锁四必要条件
| 条件 | 含义 | 破坏方法(预防) |
|---|---|---|
| 互斥(Mutual Exclusion) | 资源排他,同时只能一个进程用 | 改用共享资源(只读文件/无锁结构),多数资源难破坏 |
| 占有并等待(Hold and Wait) | 持有资源的同时申请新资源 | 一次性申请全部所需资源 |
| 不剥夺(No Preemption) | 资源不可强抢,只能主动释放 | 申请不到就释放已占资源;允许抢占 |
| 循环等待(Circular Wait) | 存在 {P0→P1→...→P0} 等待环 | 资源有序分配(按编号升序申请) |
记忆:四个全中才死锁,破坏任一即预防。互斥/不剥夺是资源固有属性难改,预防主要从占有等待、循环等待下手。
二、四种处理策略对比
| 策略 | 核心思想 | 死锁是否发生 | 代价 | 适用场景 |
|---|---|---|---|---|
| 预防 | 破坏四条件之一 | 绝不发生 | 资源利用率与并发度低 | 实时/嵌入式、资源种类少 |
| 避免 | 分配前判断是否进入不安全状态(银行家) | 不发生 | 需预知最大需求、每次分配要运算 | 资源需求可预知的批处理/数据库 |
| 检测恢复 | 允许发生,周期检测后恢复 | 可能发生 | 检测开销、恢复时杀进程/回滚 | 数据库事务死锁 |
| 鸵鸟 | 忽略,假装不会发生 | 可能发生 | 偶发死锁需人工重启 | Linux/Windows 通用 OS |
严格度:预防 > 避免 > 检测 > 鸵鸟(越严格越不死锁,但代价越大)。
三、银行家算法步骤
四个数据结构(资源类数 m、进程数 n):
| 名称 | 类型 | 含义 |
|---|---|---|
| Available | 长度 m 向量 | 各类资源当前剩余可用数 |
| Max | n×m 矩阵 | 每个进程对每类资源的最大需求 |
| Allocation | n×m 矩阵 | 每个进程当前已分配到的资源 |
| Need | n×m 矩阵 | 还可能申请的资源 = Max − Allocation |
请求处理(Pi 申请 Request[i]):
1. 若 Request[i] > Need[i]:报错(超声明)
2. 若 Request[i] > Available:Pi 等待(资源不足)
3. 试探分配:Available −= Request[i]; Allocation[i] += Request[i]; Need[i] −= Request[i]
4. 跑安全性算法:
安全 → 正式分配
不安全 → 回滚试探,Pi 等待安全性算法:
Work = Available(可用工作向量)
Finish[i] = false(所有进程未完成)
循环:
找一个 Finish[i]==false 且 Need[i] <= Work 的进程 Pi
若找到:Work += Allocation[i](Pi 完成,归还资源); Finish[i] = true
若找不到:跳出
若所有 Finish[i]==true → 安全(有安全序列)
否则 → 不安全四、死锁 vs 饥饿 vs 活锁
| 死锁 | 饥饿 | 活锁 | |
|---|---|---|---|
| 状态 | 永久阻塞,不动 | 可调度,长期无资源 | 在运行,无进展 |
| 是否阻塞 | 是 | 否 | 否 |
| 原因 | 互相等待对方资源 | 调度不公(优先级低) | 互相让步响应 |
| 例子 | 两把锁互等 | SJF 下长作业等不到 CPU | 走廊相遇同步让路 |
| 自行恢复 | 否 | 可能 | 可能(随机退避) |
| CPU 占用 | 低 | 不一定 | 可能高 |
关系:死锁一定伴随饥饿,饥饿不一定是死锁。活锁更隐蔽(监控看线程"活着"但产出为零)。
五、易错点清单
- "四个条件满足就一定死锁":错。四条件是必要条件(全满足才可能死锁),但多实例资源时还需循环等待实际成立才死锁(有环不一定死锁)。
- "资源分配图有环就是死锁":错。只有每类资源单实例时"有环⇔死锁";多实例有环不一定死锁,需图化简。
- "不安全状态就是死锁":错。不安全只是有死锁风险(可能找不到安全序列),不一定真的死锁——可能后续请求恰好能被满足。银行家是保守地拒绝进入不安全状态。
- "破坏任一条件都能预防死锁":对(四条件是必要条件),但破坏互斥/不剥夺往往不可行(资源固有属性),实际多破坏占有等待或循环等待。
- "银行家算法能用在所有 OS":错。它要求预知每个进程最大需求,通用程序无法预估,且每次分配运算开销大,通用 OS 不用。
- "Linux 用银行家算法避免死锁":错。Linux/Windows 用鸵鸟策略(忽略死锁),不预防也不避免。
- "饥饿就是死锁":错。饥饿进程还能被调度(只是轮不到资源),死锁进程永久阻塞。死锁一定饥饿,反之不然。
- "活锁是死锁的一种":错。活锁进程没阻塞、在运行(互相让步),死锁进程完全卡死。两者都无进展,但机理不同。
- "资源有序分配破坏了互斥":错。资源有序分配破坏的是循环等待(让请求方向单调,成不了环),不是互斥。
- "死锁能自己解开":错。死锁是永久的,不会因多等而消失,必须外部干预(杀进程/抢占/重启)。