文章目录
- 2. 死锁
- 2.1 死锁的必要条件
- 2.2 死锁预防
- 2.3 死锁避免
- 2.3.1 银行家算法
- 2.4 死锁检测与死锁解除
- 2.4.1 进程-资源分配图
- 2.4.2 死锁检测的步骤
- 2.4.3 死锁解除方法
2. 死锁
2.1 死锁的必要条件
-
互斥
资源必须处于非共享模式,即因此只能有一个进程访问。如果有另一个进程申请该资源,那么必须等到该资源被释放为止。
-
占有且等待
指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程阻塞,但又对自己已获得的资源保持不放。
-
不可抢占
已经分配给一个进程的资源不能强制地被抢占,它只能被占有它的进程主动释放。
-
循环等待
若干进程之间形成一种头尾相接的循环等待资源的关系(如A等待B,B等待C,C等待A)
只有同时满足这四个必要条件,才会发生死锁。
2.2 死锁预防
死锁预防是采用某种策略,限制并发进程对资源的请求,从而使得死锁的必要条件在系统执行的任何时间上都不满足。
只要破坏任何一个死锁的必要条件,就可以预防死锁的发生。但是一般比较实用的是通过破坏第二个和第四个必要条件入手。
-
破坏互斥条件
对于只读文件、磁盘等资源可采用这种办法处理。但往往有很多资源是不能同时访问的 ,所以这种做法在大多数的场合是行不通的。
-
破坏占有且等待条件——一次性申请全部资源(静态分配策略)
一个进程必须在执行前就申请到它所需要的全部资源,并且直到它所要的资源都得到满足之后才开始执行。
这个方法的缺点是可能导致资源利用率和进程并发性降低。因为在每个进程所占有的资源中,有些资源是在比较靠后的执行时间里采用的,甚至有些资源是在额外的情况下才使用的,这样就可能造成了一个进程占有了一些几乎不用的资源而使其他需要该资源的进程产生等待的情况。
-
破坏不可抢占条件
这是一种剥夺式方法,但目前一般仅适用于主存资源和处理器资源的分配,并不适用于所有的资源,会导致资源利用率下降。
-
破坏循环等待条件——对资源编号(层次分配策略)
对系统资源事先进行编号,规定进程请求所需资源的顺序必须按照资源的编号依次执行。
在层次分配策略下,所有的资源被分成了多个层次,一个进程得到某一层的一个资源后,它只能再申请较高一层的资源;当一个进程要释放某层的一个资源时,必须先释放所占用的较高层的资源,按这种策略,是不可能出现循环等待链的,
这种方式可以有效==提高了资源的利用率和系统吞吐量,但是增加了系统开销,增大了进程对资源的占用时间==。
2.3 死锁避免
死锁预防通过破坏死锁的四个必要条件之一来实现,会存在资源利用率和运行效率降低的问题。
死锁避免,允许系统中同时存在死锁的四个必要条件,根据并发进程中与每个进程有关的资源动态申请的情况,做出合理明智的选择,可以避免死锁。
- 死锁避免,是指系统在分配资源时,根据资源的使用情况提前做出预测,从而避免死锁的发生。
- 死锁避免是在程序运行时进行的。每当为申请的进程分配资源之前先测试系统状态,如果把资源分配给申请进程会产生死锁,则拒绝分配,否则为它分配资源。
- 系统状态可以分为安全状态与不安全状态。安全状态:如果操作系统能够保证所有的进程在有限的时间内得到需要的全部资源,则称系统处于安全状态。否则,系统是不安全的。
- 系统处于安全状态则不会发生死锁,若处于不安全状态则可能发生死锁。
死锁的避免(银行家算法)解决了资源使用率低的问题 ,但是它要不断地检测每个进程对各类资源的占用和申请情况,以及做安全性检查,需要花费较多的时间。
2.3.1 银行家算法
死锁避免是通过使系统保持安全状态实现的,而保持安全状态是通过银行家算法实现的。
银行家算法简要概括:当一个进程申请资源的时候,银行家算法先试探性地分配给该进程资源,然后通过安全性算法判断分配后系统是否处于安全状态
- 如果不安全,则试探分配作废,让该进程继续等待
- 如果安全,则真正分配资源给该进程
进程Pi包括:
- 进程Pi的需求资源数量(也是最大需求资源数量,MAX)
- 已分配给该进程的资源A(Allocation)
- 还需要的资源数量N(Need=M-A)
操作系统包括:
- Available为空闲资源数量,即资源池(注意:资源池的剩余资源数量+已分配给所有进程的资源数量=系统中的资源总量)
假设资源P1申请资源,银行家算法先试探的分配给它(当然先要看看当前资源池中的资源数量够不够)。若申请的资源数量小于等于Available,然后接着判断分配给P1后剩余的资源,能不能使进程队列的某个进程执行完毕,若没有进程可执行完毕,则系统处于不安全状态(即此时没有一个进程能够完成并释放资源,随时间推移,系统终将处于死锁状态)。
若有进程可执行完毕,则假设回收已分配给它的资源(剩余资源数量增加),把这个进程标记为可完成,并继续判断队列中的其它进程,若所有进程都可执行完毕,则系统处于安全状态,并根据可完成进程的分配顺序生成安全序列(如{P0,P3,P2,P1}表示将申请后的剩余资源Work先分配给P0–>回收(Work+已分配给P0的A0=Work)–>分配给P3–>回收(Work+A3=Work)–>分配给P2–>······满足所有进程)。
举例:
在银行家算法中,若出现下述资源分配情况:
注:题中共四种资源,P0的Allocation为(0,0,3,2)表示已分配给P0的第一种资源和第二种资源为0个,第三种资源3个,第四种资源2个。
- 该状态是否安全?
利用安全性算法对上面的状态进行分析(见下表),找到了一个安全序列{P0,P3,P4,P1,P2},故系统是安全的。
-
若进程P2提出请求Request(1,2,2,2)后,系统能否将资源分配给它?
P2发出请求向量Request(1,2,2,2),系统按银行家算法进行检查:
-
Request(1,2,2,2)<= Need(2,3,5,6)
-
Request(1,2,2,2)<= Available(1,6,2,2)
-
系统先假定可为P2分配资源,并修改Available,Allocation和Need向量:
- Available=(0,4,0,0)
- Allocation=(2,5,7,6)
- Need=(1,1,3,4)
-
此时再进行安全性检查,发现 Available=(0,4,0,0) 不能满足任何一个进程,所以判定系统进入不安全状态,即不能分配给P2相应的Request(1,2,2,2)。
-
2.4 死锁检测与死锁解除
死锁检测,是指不试图阻止死锁,而是当监测到死锁发生时,采取措施进行解除。
这种方法对资源的分配不加以任何限制,也不采取死锁避免措施,但系统定时地运行一个 “死锁检测”的程序,判断系统内是否出现死锁,如果检测到系统发生了死锁,再采取措施去解除它。
2.4.1 进程-资源分配图
操作系统中的每一时刻的系统状态都可以用进程-资源分配图来表示,进程-资源分配图是描述进程和资源申请及分配关系的一种有向图,可用于检测系统是否处于死锁状态。
每个方框表示每个资源类,方框中的黑点表示该资源类中的各个资源,每个进程用圆圈表示,用有向边来表示进程申请资源和分配资源的情况。
每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现(不适用于每种类型多个资源)。从一个节点出发进行深度优先搜索,对访问过的节点进行标记,如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。
图中 2-21是进程-资源分配图的一个例子,其中共有三个资源类,每个进程的资源占有和申请情况已清楚地表示在图中。在这个例子中,由于存在占有和等待资源的环路,导致一组进程永远处于等待资源的状态,发生了死锁。
进程-资源分配图中存在环路并不一定是发生了死锁。但是不存在环路,一定不会发生死锁。因为循环等待资源仅仅是死锁发生的必要条件,而不是充分条件。
图 2-22 便是一个有环路而无死锁的例子。虽然进程 P1 和进程 P3 分别占用了一个资源 R1 和一个资源 R2,并且因为等待另一个资源 R2 和另一个资源 R1 形成了环路,但进程 P2 和进程 P4 分别占有了一个资源 R1 和一个资源 R2,它们申请的资源得到了满足,在有限的时间里会归还资源,于是进程 P1 或 P3 都能获得另一个所需的资源,环路自动解除,系统也就不存在死锁状态了。
2.4.2 死锁检测的步骤
基于进程-资源分配图实现死锁检测的原理,可以利用下面的死锁检测步骤编写一个死锁检测程序,检测系统是否发生了死锁。
-
如果进程-资源分配图中无环路,则此时系统没有发生死锁。
-
如果进程-资源分配图中有环路,
-
且每个资源类仅有一个资源,则系统中已经发生了死锁。
-
且涉及到的资源类有多个资源,此时系统未必发生了死锁。
如果能在进程-资源分配图中找到一个既不阻塞又非独立的进程,该进程能够在有限的时间内归还占有的资源,即把有向边给消掉了,重复此过程,直到能在有限的时间内消除所有的边,则不会发生死锁。否则,就会发生死锁。
-
2.4.3 死锁解除方法
当死锁检测程序监测到死锁发生时,应设法让其解除,让系统从死锁状态中恢复过来。
-
立即结束所有进程的执行,重新启动操作系统
这种方法简单,但是会使之前的工作全部作废,损失很大。
-
撤销涉及死锁的所有进程,解除死锁后继续运行
这种方法能够彻底打破死锁的循环等待条件,但将付出很大代价,例如有些进程可能已经计算了很长时间,由于被撤销而使产生的部分结果也被消除了,再重新执行时还要再次进行计算。
-
逐个撤销涉及死锁的进程,回收其资源直至死锁解除
-
抢占资源
从涉及死锁的一个或几个进程中抢占资源,把抢到的资源再分配给涉及死锁的进程直至死锁解除。