Skip to content

银行家算法

2026 大纲 二(四)3 死锁避免

不改规则,只在每次分配前算一算

上一节的死锁预防很有效,但代价也明摆着:它从条件上就把路堵死了。 比如资源有序分配法要求所有进程按固定序号申请资源—— 可实际程序未必是那个顺序,硬改就得改代码,而且资源利用率会掉下来

避免换了个思路:四个必要条件一个都不破坏, 只是在每次分配之前先试算一下——如果批准这次请求之后, 系统仍然能找到一条路让所有进程都跑完,就批;否则就让它等。

这里的关键是"仍然能找到一条路",它有个名字叫安全状态存在一个安全序列,使得按这个顺序执行,每个进程都能拿到它还需要的全部资源并跑完。

⚠️ 要立住一处口径:不安全状态不等于死锁。 不安全只是说"可能走到死锁",系统仍然可以侥幸不死; 但银行家算法宁可保守——它的目标是使系统永远不进入不安全状态

算法本身就是把上面那句话翻译成四步: 假设手上的可用资源是 Work、所有进程都还没完成 → 找一个"还需要的量 ≤ Work"的进程 → 让它跑完并归还全部已占资源(Work += Allocation)→ 重复,全部完成即安全。

⚠️ 两处最容易错的地方要先钉住: 第 2 步比的是 Need(还需要多少)不是 Request(这次要多少)第 3 步加的是 Allocation(它手上已有的全部)不是 Need

交互可视化

加载可视化中...

一、安全状态:死锁避免的全部理论基础

教材原话是"虽然并非所有不安全状态都必然会转为死锁状态,但当系统进入不安全状态后,就有可能进入死锁状态"。"不安全 ≠ 死锁"决定了银行家算法是保守的:它会拒掉一些其实不会死锁的请求,代价是资源利用率不如"检测+解除"路线,收益是永远不会真的死锁。

二、四张表

数据结构维度含义
Available1×m各类资源当前的可用数量,随分配与回收动态改变
Maxn×m每个进程对各类资源的最大需求,进程进入系统时必须申明,且不应超过系统资源总量
Allocationn×m每个进程当前已分配到的各类资源数
Needn×m每个进程尚需的各类资源数,由 Max − Allocation 推出

三、安全性算法

1. 初始化:
   Work = Available          // 工作向量:系统当前可提供的资源
   Finish[i] = false         // 所有进程标记为未完成

2. 找一个同时满足两条的进程 P_i:
   Finish[i] == false   且   Need[i] <= Work

3. 找到就:
   Work = Work + Allocation[i]   // 模拟它跑完,归还全部已占资源
   Finish[i] = true
   回到步骤 2

4. 若最终所有 Finish[i] == true → 安全,记录下来的顺序就是安全序列
   否则 → 不安全

步骤 2 里"随便挑一个 NeedWork 的进程"这种贪心做法,与穷举全部 n! 种顺序的判定结果完全一致。交换论证:Work 在整个过程中只增不减(每轮加上一个非负的 Allocation),所以某个进程此刻满足 NeediWork,在任何更晚的时刻仍然满足——先做它不会让任何其他进程失去机会。因此贪心不会漏掉解。

四、资源请求处理:三道关

检查不通过怎么办为什么要有这一关
RequestiNeedi认为出错——它所需要的资源数已超过它宣布的最大值Max 是进程自己申明的承诺,超了说明进程行为不合法
RequestiAvailable尚无足够资源,Pi 须等待物理可行性:系统当下拿不出这么多,无从试探分配
试探分配后安全性检查通过作废本次试探分配,恢复原状态,让 Pi 等待物理够了,但分完之后可能失去"所有进程都能跑完"的保证

试探分配(第 ③ 关之前)要同时改三处:

Available    = Available    - Request_i
Allocation_i = Allocation_i + Request_i
Need_i       = Need_i       - Request_i

关的顺序不能乱:②不过就不必做③——系统连资源都拿不出来,谈不上试探分配。判据一句话:先看拿不拿得出来,再看敢不敢给。

一套完整手算:算 Need 与 Available、跑一轮安全性检查、再处理两个走向不同的请求(想看清每一轮 Work 怎么变、什么时候能立即判不安全时展开)

系统有 A、B、C 三类资源,总量 (12, 8, 9),4 个进程当前状态:

进程Max (A,B,C)Allocation (A,B,C)Need = Max − Allocation
P06, 2, 43, 1, 23, 1, 2
P14, 5, 32, 3, 12, 2, 2
P28, 1, 54, 0, 34, 1, 2
P33, 4, 21, 2, 12, 2, 1

第 1 步:算 Need。 逐格做减法,结果见上表第三列。Need 是安全性算法唯一要比较的量,而题目通常只给 Max 与 Allocation。

第 2 步:算 Available。 Work 的初值就是 Available,算错了后面全错。

已分配合计=(3+2+4+1, 1+3+0+2, 2+1+3+1)=(10,6,7)Available=(12,8,9)(10,6,7)=(2,2,2)

第 3 步:跑安全性算法。 Work 初值 (2,2,2),Finish 全为 false。

轮次Work (A,B,C)逐个试选中Work += Allocation
12, 2, 2P0 Need(3,1,2):A 需 3 > 2 ✗
P1 Need(2,2,2) ≤ (2,2,2) ✓
P1(2,2,2)+(2,3,1) = 4, 5, 3
24, 5, 3P0 Need(3,1,2) ≤ (4,5,3) ✓P0(4,5,3)+(3,1,2) = 7, 6, 5
37, 6, 5P2 Need(4,1,2) ≤ (7,6,5) ✓P2(7,6,5)+(4,0,3) = 11, 6, 8
411, 6, 8P3 Need(2,2,1) ≤ (11,6,8) ✓P3(11,6,8)+(1,2,1) = 12, 8, 9

第 4 步:判定并自检。 四个进程 Finish 全为 true → 系统处于安全状态,安全序列为 P1, P0, P2, P3。自检:末态 Work = (12, 8, 9) = 资源总量 ✓。

第 5 步:安全序列不唯一。 把 4 个进程的全部 4!=24 种排列逐一验证,其中 10 条是有效的安全序列。它们只可能以 P1P3 开头——初始 Work=(2,2,2),逐个比一遍就知道原因:

进程NeedWork=(2,2,2)能不能起步
P0(3,1,2)A:3 > 2
P1(2,2,2)三项均 ≤
P2(4,1,2)A:4 > 2
P3(2,2,1)三项均 ≤

10 条里 6 条以 P1 开头(如 P1,P0,P2,P3P1,P2,P3,P0),4 条以 P3 开头(如 P3,P0,P1,P2P3,P1,P2,P0)。上面第 3 步的表里第 1 轮只写到"P1 ✓"就停了,那是贪心的做法——按进程号从小到大扫,遇到第一个能推进的就选它;停下来不等于后面没有别的候选。

贪心与全排列穷举等价这一条,另用 200 000 组随机实例(进程数 2~5、资源类型 1~3、各项取值 0~3)逐组比对过,不一致 0 组(其中被判为安全的 114 412 组)。

第 6 步:处理一次请求——P2 请求 (2, 1, 1),过了②、倒在③。

  • 第①关:NeedP2=(4,1,2)(2,1,1)(4,1,2)
  • 第②关:Available=(2,2,2)(2,1,1)(2,2,2)
  • 试探分配:
原值变化新值
Available(2,2,2)−(2,1,1)(0, 1, 1)
Allocation[P2](4,0,3)+(2,1,1)(6, 1, 4)
Need[P2](4,1,2)−(2,1,1)(2, 0, 1)
  • 对新状态跑安全性算法,Work=(0,1,1)
进程Need与 Work=(0,1,1) 比较能推进吗
P0(3,1,2)A:3 > 0
P1(2,2,2)A:2 > 0
P2(2,0,1)A:2 > 0
P3(2,2,1)A:2 > 0

第一轮就找不到可推进的进程,即可立即判定不安全,不必再循环。根因很清楚:A 类资源被 P2 一次拿走 2 个后只剩 0,而四个进程的 Need 在 A 上都 ≥ 2。于是撤销试探分配,三处数值恢复为 Available=(2,2,2)、Allocation[P2]=(4,0,3)、Need[P2]=(4,1,2),让 P2 等待

第 7 步:对照——P0 请求 (3, 0, 0),在第②关就被挡下。 第①关 (3,0,0)NeedP0=(3,1,2) ✓;第②关 Available=(2,2,2),A 类需要 3 但只有 2 → 不通过,直接阻塞 P0,不进入试探分配——系统根本拿不出 3 个 A,做安全性检查是白费功夫。

五、算法的局限性

局限说明根因
需要预知 Max每个新进程进入系统时必须申明各类资源的最大需求没有 Max 就算不出 Need,安全性算法失去比较对象
效率低每次分配都要执行一遍安全性检查复杂度约 O(n2m)n 为进程数、m 为资源类数
进程数固定不适合进程数动态变化的系统进程动态增减会让 Max/Allocation 矩阵不断重建
偏保守会拒掉一些其实不会死锁的请求它按最坏情况(Need)判定,而进程未必真的会要到 Max

考点速记

  1. 银行家算法属于死锁避免不破坏任何必要条件,而在每次分配前试算,只批准仍处于安全状态的请求。实质是使系统不进入不安全状态。
  2. ⚠️不安全状态 死锁:不安全只表示可能发展成死锁,并非一定死锁;而安全状态则一定不会死锁
  3. 安全性算法四步Work = AvailableFinishfalseNeed ≤ Work 且未完成的进程Work += Allocation 并置 Finish = true全部完成即安全
  4. ⚠️两处必错点第 2 步用 Need 不用 Request第 3 步加 Allocation 不加 Need末态的 Work 应当等于系统资源总量——这是自检的好办法。
  5. 处理一次请求要过三道关RequestNeedRequestAvailable试探性分配后跑安全性检查②不过立即阻塞、③不过回滚再阻塞。
  6. ⚠️贪心找与全排列穷举等价:只要贪心地"随便找一个能满足的就让它跑"跑不下去,系统就一定不安全——不必担心是不是换个顺序就行了。
  7. Need = Max − Allocation。题目给的表格通常只给其中两列,第三列要自己算。

这一节在真题里被考过的形式

银行家算法是 process 章计算题最密的一节——deadlock 那 13 道题里有 6 道是它, 而且六道题走的是完全相同的四步,只是数据不同。

  • 给某时刻的资源分配表,判断系统是否安全 / 求安全序列(2011-27、2012-27、2018-26、2020-27、2022-26)。⚠️ 做题时按顺序做三件事就不会错:① 先补出 Need = Max − Allocation 这一列② 算出 Available(总量减去已分配之和,题目常常不直接给);③ 按速记第三条走四步,每让一个进程跑完就把它的 Allocation 全部加回 Work。做完用速记第四条自检——末态 Work 应等于资源总量
  • 判断关于银行家算法的叙述(2013-32)。⚠️ 落点是速记第一、二条:它是避免不是预防(不破坏必要条件)、目标是使系统不进入不安全状态不安全状态不等于死锁
  • 比较死锁避免与死锁检测(2015-26,在死锁的概念与预防讲)。关键差别是避免需要 Need(资源总需求),检测不需要

复习优先级必须拿满,这是全章最稳的送分题。 四步流程练熟即可, 但每一步都要照速记第四条那两个"用哪一列"的提醒来做—— 用错列是这类题唯一的失分方式。做完务必用"末态 Work 等于资源总量"自检一遍。

易错:安全性检查第 2 步拿 Request 去比 Work要用 Need——那是它还需要多少才能跑完。

易错:第 3 步把 Need 加进 Work要加 Allocation——进程跑完归还的是它手上已有的全部。

易错:忘了先算 Need = Max − Allocation。表格常常只给两列。

易错:认为不安全状态就是死锁。不安全只是可能死锁;反过来安全状态则一定不死锁。

易错:贪心找不到安全序列时怀疑是顺序选错了。贪心与穷举等价,跑不下去就是不安全。

易错:把银行家算法归到死锁预防。它是避免——一个必要条件都没破坏。

教材出处
  • 安全状态与安全序列的定义:汤小丹《计算机操作系统》3.7.1 节,印刷 p110—p111——"所谓安全状态,是指系统能按某种进程推进顺序 (P1,P2,,Pn) 为每个进程 Pi 分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成";"虽然并非所有不安全状态都必然会转为死锁状态,但当系统进入不安全状态后,就有可能进入死锁状态。反之,只要系统处于安全状态,系统便不会进入死锁状态";"避免死锁的实质在于,系统在进行资源分配时,应使系统不进入不安全状态"。
  • 四个数据结构与 Need = Max − Allocation:同书 3.7.2 节,印刷 p112。
  • 资源请求的四个步骤:同书印刷 p112——(1) Request[i] ≤ Need[i,j] 否则"认为出错,因为它所需要的资源数已超过它所宣布的最大值";(2) Request[i] ≤ Available[j] 否则"表示尚无足够资源,Pi 须等待";(3) 试探分配并修改三处数值;(4) 执行安全性算法,"否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程 Pi 等待"。
  • 安全性算法的 Work 与 Finish:同书印刷 p112——"在执行安全算法开始时,Work := Available";"Finish……开始时先做 Finish[i] := false"。
  • 进程进入系统须申明最大需求:同书印刷 p111——"每一个新进程在进入系统时,它必须申明在运行过程中,可能需要每种资源类型的最大单元数目,其数目不应超过系统所拥有的资源总量"。

本节算例的数据为自行构造,与教材的磁带机算例(12 台磁带机、3 进程)无关,可对照阅读。

相关知识

死锁的概念与预防死锁检测与解除

真题练习