死锁
死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局。一般产生死锁的原因有竞争资源,进程间推进顺序非法两种。产生死锁的四个必要条件为:互斥条件(进程对分到的资源排它性使用),请求和保持条件(保持了部分资源又提出资源请求),不剥夺资源(进程结束前所拥有资源不可被剥夺),环路等待条件(指在死锁时,必然存在一个进程-资源环形等待链)。
预防死锁的办法
摒弃“请求和保持“条件
系统在运行之前,提前申请其在整个运行过程中的所有资源。
优点:简单、易于实现且很安全。
缺点:资源浪费,独占资源降低资源利用率,使进程延迟进行。
摒弃“不剥夺“条件
当一个已经进程提出资源请求时,如果不能立即得到满足,就释放它现在拥有的资源。
缺点:延长进程周转时间,增加系统开销,降低系统吞吐量。
摒弃“环路等待“
给系统中的所有资源按类型进行线性排队,并赋予不同的序号。
优点:资源利用率和系统吞吐量改善。
缺点:限制新类型设备的增加,进程使用各类资源顺序与系统规定顺序不同时造成资源浪费,限制用户简单自主的编程。
避免死锁的实质在于:系统进行资源分配时,如何使系统不进入不安全状态。
安全性
指进程按某种进程顺序来为每个进程分配所需资源,直到满足每个进程对资源的最大需求,使每个进程都能顺利进行。我们可以使用银行家算法来获得安全序列,避免死锁。
银行家算法中的数据结构
- 可利用资源向量Available。含有m个元素的数组,如Available[j]=K,表示系统中现有Rj类资源K个。
- 最大需求矩阵Max。一个n*m矩阵。Max[i,j]=K,表示进程 i 需要Rj类资源的最大数目为K。
- 分配矩阵Allocation。一个n*m矩阵。如Allocation[i,j]=K,表示进程已分到Rj类资源数目为K。
- 需求矩阵Need。同上。表示当前尚需的各类资源数。
银行家算法
设REQUESTi是进程Pi的请求向量,当发出资源请求时,如果请求数量小于对应的Allocation 与 Allocation。系统就可以尝试将资源分配给REQUESTi.
Available[j] :=Available[j] - REQUESTi[j];
Allocation[i,j] := Allocation[i,j] + REQUESTi[j];
Need[i,j] := Need[i,j] - REQUESTi[j];
系统先执行安全性算法检查此次资源分配后系统是否仍处于安全状态。
银行家算法实例
假定系统中有五个进程{p0,p1,p2,p3,p4}和三类资源{A,B,C},各种资源数量为10,5,7,在T0时刻分配如下:
进程\资源 | Max | Allocation | Need | Available | Finish |
---|---|---|---|---|---|
A B C | A B C | A B C | A B C | false | |
p0 | 7 5 3 | 0 1 0 | 7 4 3 | 3 3 2 | false |
p1 | 3 2 2 | 2 0 0 | 1 2 2 | false | |
p2 | 9 0 2 | 3 0 2 | 6 0 0 | false | |
p3 | 2 2 2 | 2 1 1 | 0 1 1 | false | |
p4 | 4 3 3 | 0 0 2 | 4 3 1 | false |
此时观察每个进程请求资源数,即Need,找出每种资源都<=Available的。顺序观察可得p1。此时将Available分配给进程P1,进程P1得到所需资源正常执行,并修改Available,Allocation和Need向量,执行完后释放资源,连同之前拥有的资源全数返还给Available。然后将Finish改为true。然后继续上面的步骤。如果可以顺利将所有进程变成true,则进程执行的顺序则为其安全序列。若在某时刻,Available不能满足任何一个进程的需求,此时系统进入不安全状态。此时系统不分配资源。
死锁的检测和解除
死锁的检测
可将系统中进程对资源的请求调用状况画成资源分配图。然后找到一个既不阻塞又非独立的进程结点P,在顺利情况下,可获得所需资源而继续运行,直至运行完毕,再释放所占有的全部资源,使之成为孤立的结点。再以相同方法运行其他进程,类似银行家算法。若进行一系列简化后,能消除图中所有的边,则称该图是可完全简化的。
当且仅当S状态的资源分配图是不可完全简化时,则S为死锁状态。
死锁的解除
- 剥夺资源,从其他进程剥夺足够数量的资源给死锁进程,以解除死锁状态。
- 撤销进程,按照某种顺序逐个地撤销进程,直到有足够的资源可用,使死锁状态解除。