1、产生死锁的四个必要条件并举个例子说明死锁的产生
首先我们要明白死锁的定义,死锁是两个或多个进程对资源的需求引起的冲突,可以做个比喻,就像一根独木桥上有两个人迎面走,相遇时,都在等着对方让路,但是谁也不同意退回去让对方先走,导致谁也到不了对岸。两个人就是两个程序,他们都占有桥这个资源不愿放手,于是便一直处于等待状态。
死锁的产生有四个必要条件:
①互斥使用(资源独占),任意时间内进程对其占有的资源有排他控制性,其它申请的进程必须等待
②非剥夺控制,除非是进程自动放弃对资源的占有,否则其他进程无法强制使其释放,即使它处于阻塞态
③零散请求,即进程可根据自己的需求在不同的时间发出申请,而不必集中在一起申请,当申请不到资源时,也不会改变其原先占有的资源
④循环等待,等待资源的进程形成了一个封闭的链,链中进程都在等待下一进程结束,陷入了无休止的等待当中
四个条件,破坏其一,就不属于死锁了
比如说有两个进程A和B,当前A占有打印机,B占有磁带,而它们又同时申请对方占有的设备,结果两个进程的申请都得不到满足,就进入了无休止的等待,形成死锁。
2、预防死锁的各种方法
预防死锁方法的得来是源自于它的四个必要条件
①破坏互斥条件:让资源允许共享,如SPOOLing技术就可以允许若干个进程同时产生打印数据,但是类似于SPOOLing的技术并不适用于所有的资源,如进程表等,所以破坏资源的互斥性是比较困难的,该方法并不是很好
②破坏不可剥夺条件:有两种方法,一种是当其申请的资源得不到满足时,也必须放弃其原先占有的资源;另一种方法是只适用于申请资源的进程优先级比占有该资源的进程优先级高时,如果一个进程申请的资源被其它进程占用,而申请进程的优先级较高,那么它可以强迫占有资源的进程放弃。这种方法一般适用于处理机和存储资源。
③破坏零散请求条件:一般采用静态分配策略,静态分配是指当一个进程在得到其所需要的所有资源之后才执行。采取这种机制,那么进程在执行过程中就不再申请资源了,但这种方法的效率极低,资源无法得到充分的利用。
④破坏循环等待条件:可以按照资源的特性,给资源从小到大编号,进程必须按照从小到大的顺序申请资源,且规定进程占有的资源号必须小于申请的资源号才能提出申请
这里我们可以用这种方法来解决一个哲学家就餐问题:
该问题是Dijkstra在1968年提出的,如图,在一个圆餐桌上有5份通心粉,间隔放有5把叉子,5个哲学家各自坐在一盘通心粉前。哲学家思考时,他们不作任何动作。当他们饥饿的时候,必须同时手拿两把叉子才能吃到通心粉,而且只能取得自己左手边和右手边的叉子。吃完后,叉子放回。
我们可以把五个哲学家比喻成五个进程,五把叉子就是五种资源。当哲学家们吃东西的时间相继发生时,那么每个人都可以吃到通心粉,但是若他们同时感到饥饿,并同时拿起手边的一把叉子,那么有可能五个人都因无法再取得一把叉子而永远吃不到通心粉,这就是“死锁”问题。那么我们如何运用“破坏循环等待”法来解决它呢?
我们可以给五把叉子依次编号为0~4,规定哲学家必须先拿小号叉子,再拿大号叉子,若小号叉子被占用,他就进入阻塞态。这样的话,即使五个哲学家同时伸出左手,那么第4号哲学家应该先拿0号叉子,但是0号叉子被第一个哲学家所占据,所以,4号哲学家就会因无法占有0号叉子从而无法申请4号叉子,进入了阻塞态。那么拿3号叉子的哲学家可以申请拿4号叉子,从而先吃完通心粉,释放其占据的叉子,唤醒其他哲学家进程,以此类推,大家都可以吃完通心粉。问题得到解决~
3、资源分配图的化简
①检查图中有无环路,如果没有,系统不会发生死锁,结束检测,如果有环路,继续第②步
②若环路中设计的每个资源类只有一个资源,那么系统一定是死锁,若每个资源类有多个资源,可进行第③步
③在环路中找到非阻塞非独立的进程Pi,且满足|(Pi,Ri)|+∑|(Ri,Pi)|<=M(注:(Pi,Ri)表示进程Pi向资源Ri的申请个数,(Ri,Pi)是 资源Ri给进程Pi分配的资源个数),即它可以在有限的时间内将申请获得的资源执行完毕。找到进程之后,把与该进程相连的有向边全部去掉,形成孤立结点。反复执行步骤③,知道没有进程可被简化。