死锁避免与银行家算法的核心在于通过动态检测资源分配后的系统状态是否处于“安全状态”,从而决定是否允许资源分配。安全状态指的是存在至少一个进程执行序列(即安全序列),使得所有进程都能顺利完成,且不会导致死锁。
银行家算法的基本步骤如下:
- 检查进程的资源请求是否小于等于其仍需的最大需求;
- 判断当前可用资源是否能满足该请求;
- 假设进行资源分配,检查系统是否仍处于安全状态;
- 若安全,则分配资源;否则拒绝请求。
在示例中:
- 总资源为:R₁=8, R₂=7, R₃=4;
- 已分配资源总和为:R₁=7, R₂=6, R₃=4;
- 因此剩余可用资源为:R₁=1, R₂=1, R₃=0;
- 关键限制是 R₃ 的剩余为 0,因此任何需要 R₃ 的进程都无法立即执行。
分析各序列:
- 序列①和②尝试以 P₁ 或 P₂ 开始,但它们都需要 R₃ 资源,而 R₃ 可用为 0,无法满足需求,故不安全;
- 序列③以 P₄ 开始:P₄ 还需 (1,0,0),当前可用 (1,1,0) 可满足;P₄ 执行后释放资源,更新可用资源,后续进程可依次完成,形成安全序列;
- 序列④虽开始可行,但在执行到 P₅ 后导致后续如 P₁ 等无法满足资源需求,破坏安全性。
最终结论:只有序列③是安全序列,系统处于安全状态。
银行家算法虽然能有效避免死锁,提高资源利用率,但需要预先知道每个进程的最大资源需求,并频繁进行安全状态检测,带来一定系统开销。
银行家算法中“安全序列”的计算是通过模拟资源分配过程,检查是否存在一个进程执行顺序,使得所有进程都能顺利完成。其核心是安全性检测算法(Safety Algorithm),具体步骤如下:
一、数据结构定义
设系统中有n个进程,m类资源:
- Available[1…m]:每类资源当前可用数量;
- Max[n][m]:每个进程对各类资源的最大需求;
- Allocation[n][m]:每个进程当前已分配的资源数;
- Need[n][m] = Max - Allocation:每个进程仍需的资源数;
- Work[1…m]:表示当前可用来分配的资源,初始为 Available;
- Finish[n]:布尔数组,表示各进程是否已执行完成,初始为 False。
二、安全序列计算步骤(安全性算法)
1. 初始化: Work = Available Finish[i] = false 对所有 i ∈ [0, n-1] 2. 寻找满足条件的进程 Pi: a. Finish[i] == false b. Need[i] ≤ Work (即 Pi 所需资源不超过当前可用) 3. 若找到这样的 Pi: - 假设 Pi 能获得所需资源并完成执行 - Work = Work + Allocation[i] (Pi 完成后释放资源) - Finish[i] = true - 将 Pi 加入安全序列末尾 - 回到步骤 2 继续查找 4. 若所有进程 Finish[i] 都为 true: - 系统处于安全状态,输出的安全序列为一个可行执行顺序 - 否则,系统处于不安全状态,无安全序列三、示例说明(基于你提供的场景)
已知:
- 可用资源:Available = (1, 1, 0)
- 进程 P₄ 还需资源:Need[P₄] = (1, 0, 0),且 Allocation[P₄] = (1, 2, 1)
执行安全性检测:
- 检查各进程 Need 是否 ≤ Work=(1,1,0):
- P₄: Need=(1,0,0) ≤ (1,1,0) → 满足 → 可执行
- 执行 P₄:
- Work += Allocation[P₄] = (1+1, 1+2, 0+1) = (2,3,1)
- Finish[P₄] = true
- 更新后继续检查其他进程,发现更多进程可以被满足(如 P₂、P₁ 等),最终所有进程均可完成。
→ 得到一个完整的进程执行序列,例如:P₄ → P₂ → P₁ → P₅ → P₃
该序列即为一个安全序列。
四、注意点
- 安全序列可能不唯一,只要存在至少一个即可判定系统安全;
- 安全性检测是在每次资源请求前进行的“预演”;
- 若找不到任何满足 Need[i] ≤ Work 的未完成进程,则系统处于不安全状态。