死锁产生的条件及其如何处理

一、原因与条件

产生死锁的原因主要是:

  1. 因为系统资源不足。
  2. 进程运行推进的顺序不合适。
  3. 资源分配不当等。

发生死锁的四个必要条件:

  1. 相互排斥:所涉及的资源必须不可共享;否则,将不会阻止进程在必要时使用资源。
  2. 保留并等待或部分分配:进程在等待其他(请求的)资源时必须保留已分配的资源。如果该进程必须在请求一个或多个新资源时释放其资源,则不会发生死锁,因为该进程不会阻止其他人使用它控制的资源。
  3. 无抢占:在使用该资源时,不得剥夺进程资源。否则,死锁将不会发生,因为操作系统可以简单地从运行的进程中获取足够的资源以使任何进程都能完成。
  4. 资源等待或循环等待不存在:一个循环的流程链,每个流程都拥有资源,该资源当前由链中的下一个流程所请求。如果是这样,则循环定理(指出“资源图中的循环对于发生死锁是必要的”)表明可能发生死锁

如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。

 

二、处理死锁的基本方法

死锁预防:通过设置某些限制条件,去破坏死锁的四个条件中的一个或几个条件,来预防发生死锁。但由于所施加的限制条件往往太严格,因而导致系统资源利用率和系统吞吐量降低。

死锁避免:允许前三个必要条件,但通过明智的选择,确保永远不会到达死锁点,因此死锁避免比死锁预防允许更多的并发。

死锁检测:不须实现采取任何限制性措施,而是允许系统在运行过程发生死锁,但可通过系统设置的检测机构及时检测出死锁的发生,并精确地确定于死锁相关的进程和资源,然后采取适当的措施,从系统中将已发生的死锁清除掉。

死锁解除:与死锁检测相配套的一种措施。当检测到系统中已发生死锁,需将进程从死锁状态中解脱出来。常用方法:撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程。死锁检测盒解除有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。

2.1 死锁预防

在程序运行之前预防发生死锁:防死锁算法可确保至少一种必要条件(互斥,保留和等待,无抢占和循环等待)不成立。但是,大多数预防算法的资源利用率很低,因此导致吞吐量降低。

  • 破坏互斥条件:它是设备的固有属性所决定的,不仅不能改变,还应该加以保证。由于无法安全地共享某些资源,因此无法                            始终通过防止相互排斥(使所有资源可共享)来防止死锁。
  • 破坏占有和等待条件:我们将看到两种方法,但都有其缺点。
  1. 资源可以在开始执行之前获取所有必需的资源。这样可以避免死锁,但是由于进程占用了资源,即使不需要时也会减少吞吐量。在这段时间内,它们可能已被其他进程使用。
  2. 第二种方法是仅在资源不占用任何其他资源时才请求该资源。这可能会导致饥饿,因为所有必需资源可能无法始终免费提供。
  • 破坏不可抢占条件:我们将在此处看到两种方法。这里的挑战是,只有当我们可以保存当前状态并且可以从已保存状态稍后重新启动进程时,才能抢占资源。
  1. 如果处理请求由另一个等待资源持有的资源,则可以将该资源从另一个等待资源中抢占。
  2. 在第二种方法中,如果某个流程请求的资源不容易获得,那么它将抢占该资源所拥有的所有其他资源。  
  • 破坏环路等待:为了避免循环等待,可以对资源进行排序,并且我们可以确保每个进程只能按这些数字的递增顺序请求资源。该算法本身可能会增加复杂性,也可能导致不良的资源利用。

2.2 死锁避免

两种死锁避免算法:

  • 进程启动拒绝:如果一个进程的请求会导致死锁,则不启动该进程。
  • 资源分配拒绝:如果一个进程增加的资源请求会导致死锁,则不允许此分配(银行家算法)。

如您所见,大多数预防算法的资源利用率很低,因此导致吞吐量降低。相反,我们可以尝试通过使用有关进程对资源使用的先验知识来避免死锁,这些知识包括可用资源,分配的资源,将来的请求以及将来的进程发布。

大多数避免死锁算法都需要每个进程预先告知可能需要的每种类型的最大资源数量。根据所有这些信息,我们可以决定进程是否应该等待资源,从而避免循环等待的机会。

避免死锁算法会尽量避免为进程分配资源,否则会导致系统处于不安全状态。 由于在某些情况下不会立即进行资源分配,因此避免死锁算法还存在资源利用率低的问题。

安全状态 定义:如果没有死锁发生,并且即使所有进程突然请求对资源的最大需求,也仍然存在某种调度次序能够使得每一个进程运行完毕,则称该状态是安全的。安全的流程顺序和资源分配可确保安全状态。

通常我们可以使用资源分配图来避免死锁。如果资源分配图中没有周期,则没有死锁。如果存在周期,则可能出现死锁。如果每种资源只有一个实例,则一个循环意味着出现死锁。资源分配图的顶点是资源和过程。资源分配图具有请求边缘和分配边缘。从进程到资源的边缘是请求边缘,从资源到进程的边缘是分配边缘。平滑的边缘表示将来可能会提出请求,并以虚线表示。基于平滑的边缘,我们可以查看是否有周期的机会,然后批准请求,以使系统再次处于安全状态。

考虑具有平滑边缘的图像,如下所示:

如果将R2分配给p2,并且如果P1请求R2,则将出现死锁。P1占据着R1等待着R2,P2占据着R2等待着R1。

如果一个资源有多个实例,则资源分配图不是很有用。在这种情况下,我们可以使用Banker算法。在此算法中,每个进程必须预先告知所需的每种类型的最大资源,并以每种类型的最大可用实例为准。只有在分配确保安全状态的情况下,才进行资源分配。否则流程需要等待。

Banker的算法可以分为两部分:•安全算法(如果系统是否处于安全状态)。资源请求算法假设分配,并查看系统是否处于安全状态。如果新状态不安全,则不会分配资源,并且数据结构将还原到其先前状态;在这种情况下,进程必须等待资源。

2.2.1. 单个资源的银行家算法

一个小城镇的银行家,他向一群客户分别承诺了一定的贷款额度,算法要做的是判断对请求的满足是否会进入不安全状态,如果是,就拒绝请求;否则予以分配。

 

上图 c 为不安全状态,因此算法会拒绝之前的请求,从而避免进入图 c 中的状态。

2.2.2. 多个资源的银行家算法

上图中有五个进程,四个资源。左边的图表示已经分配的资源,右边的图表示还需要分配的资源。最右边的 E、P 以及 A 分别表示:总资源、已分配资源以及可用资源,注意这三个为向量,而不是具体数值,例如 A=(1020),表示 4 个资源分别还剩下 1/0/2/0。

检查一个状态是否安全的算法如下:

  • 查找右边的矩阵是否存在一行小于等于向量 A。如果不存在这样的行,那么系统将会发生死锁,状态是不安全的。
  • 假若找到这样一行,将该进程标记为终止,并将其已分配资源加到 A 中。
  • 重复以上两步,直到所有进程都标记为终止,则状态时安全的。

如果一个状态不是安全的,需要拒绝进入这个状态。

2.2.3 安全性算法

安全性算法是由银行家算法改进的其更通用。

安全性算法具体步骤描述,其中 i是进程,j是资源
(1) 设置两个向量: 在执行安全算法开始时,Work∶=Available; Finish[i]:= False;
(2) 从进程集合中找到一个能满足下述条件的进程: ① Finish[i]= False; ② Need[i,j]≤Work[j];
      若找到, 执行步骤(3), 否则,执行步骤(4)。
(3) 当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
      Work[j]∶= Work[j]+ Allocation[i, j];
      Finish[i]∶= true; go to step 2;
(4) 如果所有进程的Finish[i]=true都满足, 则表示系统处于安全状态;否则,系统处于不安全状态。

图 a 的第二列 Has 表示已拥有的资源数,第三列 Max 表示总共需要的资源数,Free 表示还有可以使用的资源数。从图 a 开始出发,先让 B 拥有所需的所有资源(图 b,Has:2+2 因为A与C Max-Has>Free ),运行结束后释放 B,此时 Free 变为 5(图 c,B占用的资源释放);接着以同样的方式运行 C 和 A,使得所有进程都能成功运行,因此可以称图 a 所示的状态时安全的。

安全状态的检测与死锁的检测类似,因为安全状态必须要求不能发生死锁。下面的银行家算法与死锁检测算法非常类似,可以结合着做参考对比。

2.3 死锁检测与解除

不试图阻止死锁,而是当检测到死锁发生时,采取措施进行恢复。

2.3.1 鸵鸟策略

把头埋在沙子里,假装根本没发生问题。

因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。

当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。

大多数操作系统,包括 Unix,Linux 和 Windows,处理死锁问题的办法仅仅是忽略它。

2.3.2 每种类型一个资源的死锁检测

上图为资源分配图,其中方框表示资源,圆圈表示进程。资源指向进程表示该资源已经分配给该进程,进程指向资源表示进程请求获取该资源。

图 a 可以抽取出环,如图 b,它满足了环路等待条件,因此会发生死锁。

每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现,从一个节点出发进行深度优先搜索,对访问过的节点进行标记,如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。

2.3.3 每种类型多个资源的死锁检测

上图中,有三个进程四个资源,每个数据代表的含义如下:

  • E 向量:资源总量
  • A 向量:资源剩余量
  • C 矩阵:每个进程所拥有的资源数量,每一行都代表一个进程拥有资源的数量
  • R 矩阵:每个进程请求的资源数量

进程 P1 和 P2 所请求的资源都得不到满足,只有进程 P3 可以,让 P3 执行,之后释放 P3 拥有的资源,此时 A = (2 2 2 0)。P2 可以执行,执行后释放 P2 拥有的资源,A = (4 2 2 1) 。P1 也可以执行。所有进程都可以顺利执行,没有死锁。

算法总结如下:

每个进程最开始时都不被标记,执行过程有可能被标记。当算法结束时,任何没有被标记的进程都是死锁进程。

  1. 寻找一个没有标记的进程 Pi,它所请求的资源小于等于 A。
  2. 如果找到了这样一个进程,那么将 C 矩阵的第 i 行向量加到 A 中,标记该进程,并转回 1。
  3. 如果没有这样一个进程,算法终止。

2.3.4 死锁恢复

  • 利用抢占恢复
  • 利用回滚恢复
  • 通过杀死进程恢复

2.4 三种策略的对比

 

参考文献:CSDN-邪三一Github-CyC2018

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值