从进程同步的概念可以知道,当并发进程需要竞争使用资源或需要相互协作向前推进时,如果不采取同步措施,或同步措施不恰当,则很容易导致并发进程不能向前推进而陷入僵局,即死锁现象。死锁是发生在一组相互竞争或协作的进程与线程之间的一个非正常现象。
在多道程序系统中,并发执行的进程推进序列不可予测,有些推进顺序,进程可以顺利完成,这些推进顺序是合法的;而有的推进顺序会引起进程无限期地等待永远不会发生的条件而不能向前推进,造成了死锁。
产生死锁的必要条件( Conditions for Deadlock )
互斥( Mutual exclusion )条件:一个资源一次只能被一个进程所使用,即是排它性使用。
不可抢占( No preemption )条件:一个资源仅能被占有它的进程所释放,而不能被别的进程强占。
请求和保持( Hold-and-wait )条件:进程已经保持了至少一个资源,但又提出了新的资源要求,而该资源又已被其它进程占有,此时请求进程阻塞,但又对已经获得的其它资源保持不放。
环路等待( Circular wait )条件:当每类资源只有一个时,在发生死锁时,必然存在一个进程-资源的环形链。如一系统状态的资源分配图所示,P1正在等待一个P2 占用的资源R2,P2正在等待一个P1占用的资源R1。
系统在进行资源分配之前,先计算资源分配的安全性。若此次分配不会导致系统从安全状态向不安全状态转换,便可将资源分配给进程;否则不分配资源,进程必须阻塞等待。从而避免发生死锁。
资源按级分配法(避免死锁)
安全状态是指系统的一种状态,在此状态开始系统能按某种顺序(例如P1、P2……Pn)来为各个进程分配其所需资源,直至最大需求,使每个进程都可顺序地一个个地完成。这个序列(P1、P2…….Pn)称为安全序列。若系统此状态不存在一个安全序列,则称系统处于不安全状态。
例:假如系统中有P1、P2和P3三个进程和12台磁带机。各进程最大需求和T0时刻分配状态如下:
进程 最大需求 已分配 还需请求 可用
P1 10 5 5 3
P2 4 2 2
P3 9 2 7
分析T0状态,可以找到一个安全序列(P2、P1、P3),即系统按此进程序列分配资源,每个进程都可顺利完成,其步骤如下: 先将可用的3台磁带机中2台分配给P2,P2满足了最大的资源需求,在有限时间内运行完毕,释放它占有的全部资源,使可用资源数量增至5台。再将可用的5台磁带机分配给P1,最后将可用10台中7台磁带机分配给P3。 这样三进程可按照(P2、P1、P3)序列顺序地一个个执行完成,则(P2、P1、P3)序列是安全序列,T0时刻状态也是安全状态。
由安全状态向不安全状态的转换
如果在T0 状态不按安全序列进行分配,可能会导致系统进入一个不安全状态,例如在T0状态下P3中申请1台磁带机。如系统实施此次分配使系统状态由T0变为T1状态,分析T1状态安全情况。
T1时刻状态:
进程 最大需求 已分配 还需请求 可用(分配资源前) 可用(释放资源后)
P1 10 5 5 > 4
P2 4 2 2 =< 2 4
P3 9 2 8 > 4
因为找不到一个安全序列使所有进程顺序地一个个地运行完毕,所以T1状态是不安全状态,由于实施分配给1台磁带机给P3的操作会引起系统状态由安全状态T0向不安全状态下的转换,所以为了避免死锁,上述的分配只是安全检测,检测后判定这样的申请不能满足,P3为申请1台磁带机而必须阻塞等待。
利用银行家算法避免死锁
银行家算法的数据结构
可用资源向量 Available [m] m为系统中资源种类数,Available[j]=k表示系统中第j类资源数为k个。
最大需求矩阵Max[n,m] n为系统中进程数,Max[i,j]=k表示进程i对j类资源的最大需求数为中k。
分配矩阵Allocation[n,m] 它定义了系统中每一类资源当前已分配给每一进程资源数, Allocation[i,j]=k表示进程i已分得j类资源的数目为k个。
需求矩阵Need[n,m] 它表示每个进程尚需的各类资源数,Need[i,j]=k 表示进程i还需要j类资源k个。Need[i,j]=Max[i,j]-Allocation[i,j]
银行家算法
假设在进程并发执行时进程i提出请求j类资源k个后,表示为Requesti[j]=k。
系统按下述步骤进行安全检查: 如果Requesti≤Needi则继续以下检查,否则显示需求申请超出最大需求值的错误。
如果Requesti≤Available则继续以下检查,否则显示系统无足够资源,Pi阻塞等待。
系统试探把要求的资源分配给进程i并修改有关数据结构的值:
Available = Available-Requesti;
Allocationi =Allocationi+Requesti;
Needi=Needi-Requesti ;
系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态,若安全,才正式将资源分配给进程i,以完成本次分配;否则将试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
假定系统中有五个进程{P0、P1、P2、P3、P4}和三种类型资源{A、B、C},每一种资源的数量分别为10、5、7。
各进程的最大需求、T0时刻资源分配情况如下 所示。
Max(最大需求) Allocation(分配矩阵) Need(需求矩阵) Available(可用资源)
A B C A B C A B C A B C
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
试问: ①T0时刻是否安全? ②P1请求资源Request1(1,0,2)是否允许? ③P4请求资源Request4(3,3,0)是否允许?
T0时刻是否安全? 从表中可找出一个序列(P1 、 P3、 P4 、 P2 、 P0)使各进程顺序地一个个地执行完成。
Max Allocation Need Available(分配资源前) Available(释放资源后)
A B C A B C A B C A B C A B C
P0 7 5 3 0 1 0 7 4 3 =< 10 4 7 ’‘’‘’‘’‘’‘’‘ 10 5 7
P1 3 2 2 2 0 0 1 2 2 =< 3 3 2 5 3 2
P2 9 0 2 3 0 2 6 0 0 =< 7 4 5 10 4 7
P3 2 2 2 2 1 1 0 1 1 =< 5 3 2 7 4 3
P4 4 3 3 0 0 2 4 3 1 =< 7 4 3 7 4 5
安全序列为{P1、P3、P4、P2、P0},T0时刻系统是安全的。
P1请求资源Request1(1,0,2)可否允许?
Request1(1,0,2)≤Need1(1,2,2),P1请求在最大需求范围内。
Request1(1,0,2)≤ Available(3,3,2),可用资源可满足P1请求需要。
试探把要求的资源分配给进程P1并修改有关数据结构的数值:
Available = Available(3,3,2)-Request1(1,0,2)=Available(2,3,0);
Need1 = Need1(1,2,2)-Request1(1,0,2)= Need1(0,2,0);
Allocation1 =Allocation1(2,0,0)+Request1(1,0,2)=Allocation1(3,0,2);
利用安全性算法检查试探将资源分配后状态的安全性如下:
Max Allocation Need Available(分配资源前) Available(释放资源后)
A B C A B C A B C A B C A B C
P0 7 5 3 0 1 0 7 4 3 =< 10 4 7 10 5 7
P1 3 2 2 3 0 2 0 2 0 =< 2 3 0 5 3 2
P2 9 0 2 3 0 2 6 0 0 =< 7 4 5 10 4 7
P3 2 2 2 2 1 1 0 1 1 =< 5 3 2 7 4 3
P4 4 3 3 0 0 2 4 3 1 =< 7 4 3 7 4 5
因为先分配资源给P1进程符合按安全序列{P1、P3、P4、P2、P0}分配资源,所以试探将资源分配给进程P1后的状态是安全的,可将资源分配给进程P1。
P4请求资源Request4(3,3,0)是否允许?
Request4(3,3,0)≤Need4(4,3,1),P4请求在最大需求范围内。 Request4(3,3,0)≤Available(2,3,0)不成立,即可用资源暂不能满足P4请求资源需要,P4阻塞等待。
安全性算法
安全性算法执行步骤如下:
A.初始化设置工作向量Work[m]表示系统可提供的各类资源数目,用以保护原数据结构有关值。Work = Available,设置完成标志向量 Finish[n]。
Finish[i] = false 表示i进程尚末完成,如值为true则表示进程i已完成。
B.从进程集合n中找到一个能满足下述二个条件: Finish[i] = false和Necdi≤Work,如找到则执行步骤C,如找不到同时满足以上二条件的进程则执行步骤D。
C.当进程i获得资源后可顺利执行直到完成,并释放出分配给它的资源,表示如下: work = work+Allocationi ; Finish[i]=true ;转执行步骤B。
D.如果所有的Finish[i]=ture,则表示系统处于安全状态,否则系统处于不安全状态。
死锁的检测
死锁的避免算法增加了系统的开销,死锁的检测采用资源分配图的简化判断是否发生了不安全状态。
如发现系统处于不安全状态时,即执行死锁解除的策略,采用此法开销相对减少。
资源分配图简化的方法:在资源分配图中找一个既不阻塞又非孤立的进程结点PI(如某进程既无已分配的资源也不需申请资源,即既无分配边又无申请边,则该进程结点是孤立结点),让它获得所需资源而继续运行直至完毕,再释放它拥有的所有的资源,这相当于取消PI的分配边和请求边,使它成为孤立结点。
经过以上简化,如所有的进程结点都是孤立结点则称资源分配图是可完全简化的。若不能通过任何过程使该图完全简化,则该图是不可完全简化的。
死锁定理: S为死锁状态的充分条件是:尚且仅当S状态的资源分配图是不可完全简化的,该充分条件称为死锁定理。