对死锁的思考【2】/thinking in deadlocks

上一篇

对死锁的思考【1】

介绍了什么是死锁,对于每种类型一个资源和多个资源的检测,这里会介绍一下

如何从死锁中恢复

死锁的避免

死锁的预防

说明:这不是一篇专业性的文章,只是力求让读者能理解、知道什么是死锁。如果想要更具体深入的知识还需要查阅相关文献。

从死锁中恢复

抢占性恢复

从字面上看,抢占性恢复就是强制把已经被占有的资源强制拿过来,分配给需要他的进程,而达到解除死锁的目的。

在不通知持有资源进程的情况下,将资源强制占用,用完后又还给进程,这和资源本身的特性有关。即有的资源是不可抢占的。

比如说一个正在刻录光盘的光驱,在它完成之前是不可抢占的。

回滚技术

简单的说,就是再检测到死锁的时候设法回到还没发生死锁的状态。只要记录下进程执行的每一步(存储镜像, 资源状态),可以把它记录在磁盘上,当死锁发生时,根据这个记录回到还没发生死锁的状态,一般是回到上一个时间点,重新分配资源,就可以避免死锁的发生。

当进程执行时,一系列的记录文件会被累计起来,如下图:

每个进程都会对应自己的记录,当回退到时间点i 后重新分配资源,接着销毁 记录i 以后的记录。

其实回滚技术也可叫做回退技术。让执行状态退回到还没发生死锁的状态,重新分配资源。

通过杀死进程恢复

这就更好理解了,kill 在执行的进程,释放它的资源,如果它所持有的资源正好是死锁中某个进程需要的资源,那么死锁就解除了。不过这有一定的运气成分。如果运气不好kill的进程中没有解除死锁需要的资源,就要在kill别的进程。

死锁的避免

死锁的产生是由于进程之间分配资源的一种不合理性。举个例子:按照分配方法A最后进程集合发生死锁,如果能在A方法分配之前能预先知道这样的分配会最终导致死锁,那么不按照A方法分配资源,采用别的方法,或许就能避免死锁的发生。

安全状态

如果死锁没有发生,即使进程集合中的所有进程都请求最大的资源,也存在某种调度次序能使所有进程都执行,那么称这个状态是安全的。

看下面的例子:

设这里使用的资源S一共有10个

考虑进程A、B、C。如图表所示,中间一列(Has)表示进程拥有的资源右边一列(Max)表示该进程最多可能请求的资源。

图a)中资源剩余3个。

对于这个进程集合,要让进程完整的执行,A需要6个资源,B需要2个,C需要5个。

所以可以这样调度:剩余3个资源,分另个资源你给B,让它执行,状态如 b)所示。

B执行后,释放占有的资源,到达状态 c) 。这时剩余5个资源,可以执行C、然后执行A。

a)的状态通过这样的调度算法,就能让进程集合中的进程都得到执行,不会出现死锁。所以a)状态是安全的。

像这样存在一种调度方法能让进程集合中的每个进程都能执行的集合状态称为安全状态。(因为可以避免死锁)

不安全状态

和安全状态想对应,如果不能存在上面说的调度算法,就是不安全状态。

不论怎样调度进程执行,都不能让进程集合中的所有状态都得到执行的状态,就是不安全状态。

理论都是浮云来看一个例子吧:

如图:

这次不是让进程B先执行,而是先分配一个资源给A,到达如图 b)的状态,因为只剩下2个资源,只能执行B,到状态 c) ,释放B,到达状态d)

到状态d)以后,剩余资源只有4个,A和C都不够执行了。这时候进程集合中的进程就不能全部被执行。

可以看出,从b)出发,不论怎样调度程序和分配资源,最后都不能保证进程结合中的进程都被执行。

所以b)的状态是不安全状态。

不安全状态并不是死锁

比如d)中,在A请求其他资源之前,可以在自己执行之前释放一个资源,让C执行,

安全状态和不安全状态的区别是:从安全状态出发,系统可以保证所有的进程都被执行,而从不安全状态出发就没有这样的保证。

下面介绍关于上文中两种状态判断的银行家算法,

银行家算法初探

单个资源的银行家算法

银行家算法,第一次听说时也感觉这个名字挺酷的,它是一种能够避免死锁的调度算法。是上一篇博文中给出的死锁检测方法的一种扩展。

还是唠叨下吧 ,银行家算法名字的来历:

一个小镇上有一个银行家,银行家有钱啊,他借钱给一些人,对于不同的人,有不同的贷款额度,也就是最多能借给他的money。

为了使问题简单,假设有A、B、C、D四个人向他借钱。但是借钱有个条件,就是每一次有人来借钱了,就要判断是不是会进入不安全状态

如果是 ,就不借钱给他,如果借出之后仍是安全的,就借钱给他。

银行家是聪明的,他知道所有客户不会同时都需要最大的贷款额度,他拥有10个单位的money,他向客户承诺的贷款额度综合是22.

通过他的协调,就能在客户之间周旋~

看下面的图:左边的一列表示客户,中间的一列表示客户已有的money,最后一列表示他们的贷款额度。

客户都有自己的生意,不停的借钱和还钱,假设某时刻的状态如 b) 所示,剩余两个资源,银行家可以推辞除C以外的借钱请求,等C借钱用过之后释放自己的资源,系统中的剩余资源就编程了4个,这是可以接受来自B 或者 C 的请求。所以b)的状态是安全状态

如果银行家借了一个单元的钱个B,如 c)的 状态,剩余1个资源,银行家将不能满足任何客户的需求,所以状态 c)是不安全状态。

银行家算法就是对每一个请求进行检查,如果这一请求能达到安全状态,就执行,如果不能达到安全状态,就不让它执行。

要查看状态是否安全,银行家看它是否有足够的资源满足其中的一个客户,如果可以,认为这笔投资是可回收的,一次类推,如果最后所有资源都被回收,那么该状态是安全的,最初的状态也被批准。

可见,银行家算法是检查每一次的资源请求是否会达到安全状态,如果是,则批准该请求,否则禁止该请求。

死锁的预防

 资源的分配无时无刻都在发生,所以说要完全杜绝死锁的出现是不可能的,那么如何预防死锁呢?

在前一篇对死锁的思考【1】/thinking in deadlocks中,列出了死锁发生的四个必要条件,只有这四个条件都同时满足,才会发生死锁。

换一个角度,要避免死锁,只要破坏这四个条件中的一个不就可以了?对! 是这样的。请看下文

 破坏互斥条件

如果资源不被独占,那么死锁就不会发生。其中一种典型的技术称为假脱机打印机技术(spolling printer)。资源不被独占,也就是说可以同时又多个进程使用打印机。基本思想是这样的:打印机有一个专门 的工作进程,一般称为守护进程,由于该进程不会请求其它资源,所以不会发生死锁。

破坏占有和等待条件

只要禁止进程在执行的过程中请求其它资源,就不会发生死锁。简单的思路是让每个进程在执行前就分配好它需要的所有资源。但也有一个问题:许多进程在执行的时候才知道自己需要多少资源,如果事先就知道需要的资源个数, 就可以使用上文中的银行家算法来避免死锁。

破坏不可抢占条件

如果一个进程正在使用打印机,如果被其他进程强行抢占,将会引起混乱,然而对于某些特殊的资源,可以使用虚拟化的方式来实现。

如假脱机打印机技术

破换环路等待条件

这里介绍一种简单的方法:如果进程要请求另外一个资源,则必须放弃前面以请求的资源。这就可以避免环路出现

参考资料:

《modern operating system》

http://msdn.microsoft.com/en-us/library/ms178104.aspx

http://en.wikipedia.org/wiki/Deadlock

如转载请注明出处:http://www.cnblogs.com/yanlingyin/

原文地址:https://www.cnblogs.com/yanlingyin/p/deadlocks.html