3.6 预防死锁
1. 破坏“请求和保持”条件
所有进程在开始运行之前,必须一次性地申请其在整个运行过程中所需的全部资源。
- 优点:简单、易行且安全
- 缺点:①资源被严重浪费 ②使进程经常会发生饥饿现象
2. 破坏“不可抢占”条件
允许进程先运行,提出新的资源请求而不能得到满足时,必须释放已经保持的所有资源,待以后需要时重新申请。
实现比较复杂,且需付出很大代价,可能会造成进程前一阶段工作的失效,反复申请和释放资源。
3. 破坏“循环等待”条件
对系统所有资源类型进行线性排序,并赋予不同的序号,每个进程必须按序号递增的顺序请求资源。在采用这种策略后所形成的资源分配图中,不可能再出现环路。
与前两种策略比较,其资源利用率和系统吞吐量都有较明显的改善,但也存在以下问题:
3. 为系统中各类资源所规定的序号,限制了新类型设备的增加;
4. 作业使用各类资源的顺序与系统规定的顺序不同;
5. 会限制用户编程自由。
3.7 避免死锁
1. 安全状态:是指系统能按某种进程推进顺序(P1,P2,…,Pn)为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺利地完成。
(P1,P2,…,Pn)为安全序列。
6. 最终释放的总资源为所有资源总和,可检查是否计算出错。
7. 并非所有不安全状态都必然会转为死锁状态,不安全状态一旦出错才有可能转为死锁状态。
8. 只要系统处于安全状态,系统便不会进入死锁状态。
2.利用银行家算法避免死锁
- 数据结构:
①可利用资源向量Available
②最大需求矩阵Max
③分配矩阵Allocation
④需求矩阵Need - 银行家算法:
设Request是进程Pi的请求向量,如果Request[j] = K,表示进程Pi需要K个Rj类型的资源。当Pi发出资源请求后,系统按下述步骤进行检查:
①如果Request[j]≤Need[i , j],便转向步骤②;否则认为出错,因为它所需要的资源数已超过它所宣布的最大值。
②如果Request[j]≤Available[j],便转向步骤③;否则,表示尚无足够的资源,Pi须等待。
③系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
Available[j] -= Request[j];
Allocation[i , j] += Request[j];
Need[i , j] -= Request[j];
④系统执行安全性算法,检查此次资源分配后系统是否处于安全状态。若安全,才正式将资源分配给进程Pi,以完成本次分配;否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。 - 安全性算法
①设置两个向量:①工作向量Work,它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work = Available;②Finish:它表示系统是否有足够的资源分配给进程,使之运行完成。开始时先做Finish[i] = false;当有足够资源分配给进程时,再令Finish = true。
②从进程集合中找到一个能满足下述条件的进程:
Finish[i] = false;
Need[i , j] ≤ Work[j];
若找到,执行步骤③,否则,执行步骤④。
③当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Work[j] += Allocation[i , j];
Finish[i] = true;
go to step 2;
④如果所有进程的Finish[i] = true都满足,则表示系统处于安全状态;否则,系统处于不安全状态。 - 银行家算法示例
假定系统中有五个进程{P0,P1,P2,P3,P4}和三类资源{A,B,C},各种资源的数量分别为10、5、7,在T0时刻的资源分配情况如图所示。
计算举例:当前T0时刻是否安全?
利用安全性算法在下表找一个安全序列{P1,P3,P4,P2,P0},故是安全的。(最后检查应是资源释放完后又回到10、5、7 )
(1)T0时刻的初始状态是安全的;
(2)下面出现P1请求资源的操作,具体请求向量为Request1(1,0,2),利用银行家算法进行检查该操作是否是安全可行的:
1)两个基本判断
Request1(1,0,2)<=Need1(1,2,2)
Request1(1,0,2)<=Available1(3,3,2)
2)先假设为P1分配资源,并修改Available,Allocation1和Need1向量。
3) Request1(1,0,2)后新的资源状态表下再判断新资源状态是否是安全的。
找到一个安全序列{P1,P3,P4,P0,P2},因此系统是安全的,该请求是安全的,可将假设真正实施,将P1所申请的资源分配给它。
问:P4发出请求向量Request(3,3,0),可否分配资源?
1)Request(3,3,0)≤Need(4,3,1);
2)Request(3,3,0)≥Available(2,3,0),P4等待
问:P0发出请求向量Request0(0,2,0),可否分配资源?
1)Request0(0,2,0)<=Need0(7,4,3);
2)Request0(0,2,0)<=Available(2,3,0);
3)系统暂时先假定可为P0分配资源,并修改有关数据,见下表:
Available(2,1,0)不能满足任何finish=false进程的需求,如果分配会使系统进入不安全状态,所以不能分配资源。
如果把P0发出的请求向量改为Request0(0,1,0),如下图:
3.8 死锁的检测与解除
1.检测时机
- 当进程等待时检测死锁
- 定时检测
- 系统资源利用率下降时检测死锁
2.资源分配图的简化方法:
- 在资源分配图中,找出一个既不阻塞又非独立的进程结点Pi。在顺利的情况下,Pi运行完毕,再释放其所占有的全部资源。
- 由于释放了资源,这样能使其他被阻塞的进程获得资源继续运行,消去了Pi的边。
- 在进行一系列的简化后,若能消去图中所有的边,使所有的进程结点都成为孤立的结点,则称该图是可完全简化的。
3.死锁检测算法
- 每个进程和资源指定唯一编号
- 设置一张资源分配表
- 设置一张进程等待表
- 反复检测这两张表,列出所有等待与分配的关系,若出现循环等待,则出现了死锁。