操作系统死锁问题
死锁是两个及以上进程因争夺不可剥夺资源而陷入的互相等待状态,本文梳理了死锁的四个必要条件,对比了死锁与饥饿的区别,详细介绍了三种处理策略,并给出了不发生死锁的最小资源数计算公式及经典例题。
文章目录
一、核心概念
1. 死锁的定义
死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力干预,这些进程将永远无法继续执行。
2. 资源类型
理解死锁前,需要明确操作系统中资源的分类:
| 资源类型 | 含义 | 特点 | 示例 |
|---|---|---|---|
| 可剥夺资源 | 可被系统强制收回 | 不导致死锁 | CPU、内存 |
| 不可剥夺资源 | 必须由持有者主动释放 | 可能引发死锁 | 打印机、文件锁 |
| 临时性资源 | 由进程产生,使用后被消耗 | 可能引发死锁 | 信号、消息 |
| 永久性资源 | 可重复使用,数量固定 | 主要死锁来源 | I/O设备、存储空间 |
3. 死锁与饥饿的区别
| 对比项 | 死锁 | 饥饿 |
|---|---|---|
| 进程状态 | 至少两个进程相互等待,全部阻塞 | 单个进程长期得不到资源 |
| 发生原因 | 资源分配不当,形成循环等待 | 调度策略不公平 |
| 解决难度 | 必须打破循环等待链 | 调整优先级即可解决 |
| 类比 | 两人互拿对方需要的筷子,都不放手 | 一个人总被插队,永远轮不到 |
死锁是"同归于尽",饥饿是"单方面受难"。死锁至少涉及两个进程,饥饿可能只有一个"倒霉蛋"。

二、死锁产生的四个必要条件
死锁的发生必须同时满足以下四个条件,缺一不可:
| 条件 | 含义 | 说明 |
|---|---|---|
| 互斥条件 | 资源一次只能被一个进程使用 | 打印机、临界区等天然具有互斥性 |
| 请求与保持 | 进程持有资源的同时,又申请新资源 | 吃着碗里的,看着锅里的 |
| 不可剥夺 | 进程获得的资源不能被强制抢走 | 必须由持有者主动释放 |
| 循环等待 | 多个进程形成首尾相接的资源等待链 | P1等P2,P2等P3,P3等P1 |
这四个条件中,互斥条件是资源的固有属性,无法破坏;循环等待是死锁发生时的最直观表现,但不等于死锁(是必要条件而非充分条件)。
死锁的判定逻辑
- 四个条件全部满足 → 必然发生死锁
- 任意一个条件不满足 → 不会发生死锁
三、死锁的处理策略
操作系统中处理死锁的策略分为三个层次:预防、避免、检测与恢复。
| 策略 | 介入时机 | 核心思想 | 具体方法 |
|---|---|---|---|
| 死锁预防 | 系统设计阶段 | 破坏四个必要条件之一 | 静态分配、有序资源分配 |
| 死锁避免 | 系统运行阶段 | 动态判断是否进入不安全状态 | 银行家算法 |
| 死锁检测与恢复 | 死锁发生后 | 定期检测并强制解除 | 资源分配图化简、终止进程 |

1. 死锁预防
通过破坏死锁的四个必要条件之一来预防死锁:
| 破坏的条件 | 方法 | 优缺点 |
|---|---|---|
| 破坏"请求与保持" | 静态分配:进程运行前一次性申请全部资源 | 资源利用率低,可能饥饿 |
| 破坏"不可剥夺" | 进程申请新资源失败时,主动释放已持有资源 | 实现复杂,状态保存开销大 |
| 破坏"循环等待" | 有序资源分配:给资源编号,进程必须按编号递增顺序申请 | 编号难以统一,限制并发度 |
2. 死锁避免——银行家算法
银行家算法,是典型的死锁避免算法。其核心思想是:每次分配资源前,先"试探性"地判断分配后系统是否仍处于安全状态。
关键数据结构:
- Available:系统当前可用资源向量
- Max:每个进程对各类资源的最大需求
- Allocation:每个进程已分配的资源
- Need:每个进程还需要的资源(Need = Max - Allocation)
安全状态的判定:
- 假设某个进程能获得所需资源并运行完成
- 完成后释放其全部资源
- 判断是否存在一个安全序列,使所有进程都能顺利完成
"有钱才借,借了还得起。“银行家算法的本质是"稳健放贷”,只把资源借给能还款(能运行完)的进程。
3. 死锁检测与恢复
当系统不采取预防和避免策略时,需要具备检测和恢复能力。
检测方法:
- 构建资源分配图
- 若能完全化简(消除所有边),则无死锁
- 若存在无法化简的环路,则发生死锁
恢复方法:
- 进程终止:撤销所有死锁进程(代价大)或逐个撤销直到死锁解除
- 资源剥夺:强制取走某些进程的资源,分配给其他进程
- 回退:将进程回滚到死锁前的检查点重新执行
四、经典计算:不发生死锁的最小资源数
公式推导
设系统中有 n 个并发进程,每个进程需要 m 个同类资源。
最坏情况:每个进程都拿到了 m - 1 个资源,都在等待第 m 个资源。
此时需要的资源总数 = n × (m - 1)
在此基础上再加 1 个资源,就能保证至少有一个进程可以拿到 m 个资源,从而运行完成并释放资源。
公式:不发生死锁的最小资源数 = n × (m - 1) + 1
推广形式
若系统中每个进程需要的资源数不同,设第 i 个进程需要 Ri 个资源,则:
不发生死锁的最小资源数 = (R1 - 1) + (R2 - 1) + … + (Rn - 1) + 1 = Σ(Ri - 1) + 1
让所有人都"差一个"是临界状态,再多一个就能打破僵局。类比一群人分苹果,每人想要N个,最惨的情况是每人先分到N-1个,这时再来一个苹果,必然有人凑够N个。
五、练习
题目1:以下关于死锁的必要条件的叙述中,错误的是( )。
A. 互斥条件:一个资源每次只能被一个进程使用
B. 请求与保持条件:一个进程请求资源失败时,需释放已占有的资源
C. 不可剥夺条件:进程获得的资源在使用完之前不能被强行夺走
D. 循环等待条件:若干进程之间形成头尾相接的循环等待资源关系
答案:B
解析:B错误,"请求与保持"条件是指进程在保持已有资源的同时请求新资源,而非请求失败时释放资源(释放资源恰恰是破坏该条件的手段)。
题目2:某系统中有5个并发进程,每个进程都需要4个同类资源。该系统不发生死锁的最少资源数是( )。
A. 12 B. 13 C. 16 D. 20
答案:C
解析:套用公式:n × (m - 1) + 1 = 5 × (4 - 1) + 1 = 5 × 3 + 1 = 16。
题目3:某系统采用银行家算法,当前状态如下表:
| 进程 | Max | Allocation | Need | Available |
|---|---|---|---|---|
| P0 | 7 5 3 | 0 1 0 | 7 4 3 | 3 3 2 |
| P1 | 3 2 2 | 2 0 0 | 1 2 2 | |
| P2 | 9 0 2 | 3 0 2 | 6 0 0 | |
| P3 | 2 2 2 | 2 1 1 | 0 1 1 | |
| P4 | 4 3 3 | 0 0 2 | 4 3 1 |
以下哪个进程序列是安全序列?( )
A. P1, P3, P4, P0, P2
B. P1, P3, P0, P4, P2
C. P3, P1, P4, P0, P2
D. P1, P3, P4, P2, P0
答案:A
解析:
- 初始Available = (3, 3, 2)
- P1的Need = (1, 2, 2) ≤ Available,P1可完成,释放后Available变为(5, 3, 2)
- P3的Need = (0, 1, 1) ≤ Available,P3可完成,释放后Available变为(7, 4, 3)
- P4的Need = (4, 3, 1) ≤ Available,P4可完成,释放后Available变为(7, 4, 5)
- P0的Need = (7, 4, 3) ≤ Available,P0可完成,释放后Available变为(7, 5, 5)
- P2的Need = (6, 0, 0) ≤ Available,P2可完成
题目4:某系统中有R1、R2两种资源各2个,现有P1、P2两个进程。P1已获得1个R1,正在申请1个R2;P2已获得1个R2,正在申请1个R1。该状态是否发生死锁?( )
A. 是,因为满足死锁的四个必要条件
B. 否,因为可以通过剥夺资源解决
C. 是,但银行家算法可以避免
D. 否,因为资源申请可以被满足
答案:A
解析:P1持有R1等待R2,P2持有R2等待R1,形成循环等待。四个条件均满足,发生死锁。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)