第五章 分布式系统中的死锁
By齐浩坤
文章目录
死锁:进程和线程在等待其他进程和线程释放资源,但每个进程和线程又持有对方所需要的资源,导致所有进程无法继续推进(哲学家问题)
1死锁问题
一、死锁发生的条件
- 互斥:保证统一资源在同一时刻最多只能被一个进程占用,防止多个进程同时共享访问不可同时共享访问的资源
- 不可剥夺的资源分配:系统将一个资源的访问权分配给某一个进程之后,系统不能强迫该进程放弃对该资源的控制权
- 占有并等待:一个进程占用了至少一个资源,同时在等待获取被其他进程占用的资源
- 循环等待:在等待图中有一个循环路径
二、死锁的图论模型
表示死锁的图模型有两种:等待图 和 资源分配图
需要注意的是 在下面的两个图中,b图死锁了 而a图没有死锁,因为P1可以释放半个R1
在等待图中,节点代表进程,当且仅当进程Pi等待一个被进程Pj所占用的资源时,边(Pi,Pj)存在于等待图中,图中的边是有向的。
资源分配图到等待图的转化:
-
在资源分配图中找到一个未被处理的资源R。如果所有的资源都已经处理,转向步骤3。
-
从这个资源R的每个输入进程节点到每个输出进程节点之间加一条有向边。一个资源的输入进程节点是等待这个资源的进程节点,一个资源的输出进程节点是占有这个资源的进程节点。转向步骤1。
-
删除所有的资源节点以及相应的边。
三、处理死锁的策略
PAID概括处理死锁的各种方法 :预防Prevent 避免Avid 忽略Ignore 检测Detect
- 预防死锁:通过限制请求,保证死锁的四个条件中至少有一个不能发生,从而预防思索
- 避免死锁:如果资源分配会导致一个安全的结果状态,就将资源动态地分配给进程。如果至少有一个执行序列使所有的进程都能完成运行,那么这个状态就是安全的。
- 忽略死锁
- 检测死锁和从死锁中恢复:允许死锁发生,然后发现并解除死锁
四、死锁的AND条件和OR条件
AND条件就是当进程取得所有所需资源的时候,他才能继续执行
OR条件就是当进程得到至少一个所需资源,他就能继续执行
- 通信死锁:等待的资源为报文,OR条件
- 资源死锁:等待资源,AND条件
在使用AND条件的系统中,死锁条件是在等待图中存在回路。但是在使用OR条件的系统中,等待图中的回路未必会引发死锁。在使用OR条件的系统中,死锁条件是存在结(knot)。一个结K是一个节点集合,对于K中的任何节点a,a能到达K中的所有节点,并且只能到达K中的节点。
也就是几个节点形成了回路,这几个节点可以相互到达,但是到不了这几个节点之外的,例如b这里的p2、p3、p4、p5,虽然a中的p2、p3、p4也是回路,但是多了一个p5
2死锁的预防
死锁预防算法是通过限制进程的资源请求来达到预防死锁的目的,都是通过打破四个死锁条件中的一个条件来实现的。
一、一般的预防方法
- 进程在开始执行之前同时获得所有所需资源。这种方法打破了占有并等待的条件。
- 所有的资源都要被赋予一个唯一的数字编号。一个进程可以请求一个有唯一编号i的资源,条件是该进程没有占用编号小于或等于i的资源。这样,就打破了循环等待的条件。
- 每个进程被赋予一个唯一的优先级标识。优先级标识决定了进程Pi是否应该等待进程Pj,从而打破了不可剥夺的条件。
二、基于时间戳的预防死锁方法
包括两种死锁预防方案。这两种方案相互补充,这种方法常用于分布式数据库系统中。
-
等待-死亡方案:该方案是基于非剥夺方法。当进程Pi请求的资源正被进程Pj占有时,只有当Pi的时间戳比进程Pj的时间戳小时,即Pi比Pj老时,Pi才能等待。否则Pi被卷回(roll-back),即死亡。
-
伤害-等待方案:它是一种基于剥夺的方法。当进程Pi请求的资源正被进程Pj占有时,只有当进程Pi的时间戳比进程Pj的时间戳大时,即Pi比Pj年轻时,Pi才能等待。否则Pj被卷回(roll-back),即死亡。
3死锁的检测
一、集中式死锁检测
在集中式死锁检测的方法中,利用局部的资源分配图(或等待图)建立一个全局资源分配图(或等待图),任何一个机器为他自己的进程和资源维持一个局部的资源分配图,整个系统只有一个协调者,他维持全局的资源分配图,全局的资源分配图是由每个机器上的局部资源分配图组合而成的。
当开始死锁检测的时候,协调者就会查找全局等待图,如果发现了回路,一个进程就会被卷回,从而打破循环等待
全局资源分配图(或等待图)的获得方法:
- 每当局部图中有边加入或删除的时候,向协调者发送一个报文,协调者根据报文的信息对全局图进行更新
- 定期的更新,每个机器定期的向协调者发送自上次更新以来所添加和删除的边,协调者根据报文信息对全局图进行更新
- 当协调者认为需要运行回路检测算法的时候,就会要求所有的机器向它发送局部图的更新下信息,协调者对全局图进行更新
缺点:容易产生假死锁的情况
二、分布式死锁检测
在分布式死锁检测的算法当中,每台机器都保持着他们的自主性,一个局部失效不会对算法产生致命的影响。分布式死锁检测算法分为两类:第一类是每台机器上都有一个全局等待图的拷贝,从而每个机器都对系统有一个全局视图 。第二类是全局等待图被分解并分不到不同的机器上。
Knapp将分布式死锁检测分为以下四种:
- 路径推动算法
在每个机器上有简单的全局等待图,当进行死锁检测的时候,各个机器就将等待图拷贝送往一定数量的邻居节点,局部拷贝更新之后又被继续传播,直到重复道某个节点获得了足够的信息来构造一个等待图能做出是否存在死锁的结论。
- 边跟踪算法
①分布式网络结构图中的回路可以通过沿图的边传播一种叫探测器的特殊信息来检测。当一个发起者得到一个与自己发送的探测器相匹配的探测器时,它就知道它在图中的一个回路里。
- 扩散计算
怀疑有死锁发生时,事务管理器通过向依赖于它的进程发送查询启动一个扩散进程。这里不会生成全局等待图。发送查询信息时,扩散计算就增长;接收回答后,扩散计算就缩减。根据所得信息,发起者会检测到死锁的发生。
- 全局状态检测
这个方法基于Chandy和Lamport 的快照方法。可以通过建立一个一致的全局状态而无需暂停当前的计算来生成一个一致的全局等待图。
三、死锁检测和回复的研究方向
-
算法正确性。严格证明死锁检测算法的正确性是困难的,由于报文的传输延迟是不可预料的,所以得到一致的全局状态是很困难的。
-
算法性能。需要在信息流量(监测和恢复算法的复杂性)和死锁持续时间(监测和恢复的速度)之间达成妥协。
-
死锁解决。一个好而快的死锁检测算法可能并不能提供足够的信息用于解决死锁。
-
假死锁。一个检测程序不仅要满足前进要求,即必须在有限的时间内发现死锁,还要满足安全要求。如果一个死锁被发现,那么这个死锁应该是确实存在的。
-
死锁概率。检测和恢复算法的设计依赖于给定系统中死锁发生的概率。