分布式系统中的死锁处理 (Wound/Wait Mutexes reservation.c )

1死锁发生的条件

分布式计算机系统是一种具有多处理器并且各个处理器之间通过互连网络构建成一个具有整体功能的计算机系统。系统具有的优点是加快了处理的速度,简化了主机的逻辑结构,同时具有成本低和易于维护的特点,并且成为计算机应用领域发展中的一个重要方向。但是,在分布式环境下,由于通讯延迟的不确定性、地域的分布性以及资源和数据的高度共享性等影响因素的存在,使得死锁预防和检测变得极为困难。在分布式计算系统中,有两个以上的进程在并发执行,每个进程都在等待被其它的进程所占用的系统资源而不能继续运行,即导致系统中任何一个进程都无法运行下去(死循环),这就产生了死锁。

当且仅当以下四个条件同时成立时,死锁才会发生:

1) 互斥。同一个资源在同一时刻最多只能被一个进程占用。

2) 占有并等待。必然有一个进程至少占用了系统中的一个资源,同时在等待获取被其他进程占用的资源。

3) 不可剥夺。一个进程不能剥夺被其他进程占用的资源。

4) 循环等待。在等待图中有一个循环。

2 处理死锁的策略

有三种处理死锁的策略:

1) 预防死锁。限制请求,保证前文提到的四个死锁条件中至少有一个不能发生, 从而预防死锁;

2) 避免死锁。如果结果状态是安全的, 就将资源动态地分给进程。如果至少有一个执行序列使所有的进程都能完成运行, 那么这个状态就是安全的;

3) 检测死锁和从死锁中恢复, 允许死锁发生, 然后发现并解除死锁。

死锁预防和避免采用一种悲观方法,即认为死锁会经常发生并试图阻止或避免它。虽然死锁避免策略在集中式系统中广为应用,并且有许多算法,但是在分布式系统中很少使用。这是因为在分布式系统中没有全局时钟,检查安全性状态会涉及到大量进程和资源的计算,从而引起昂贵的开销。死锁检测和恢复使用乐观方法,然而这种方法对于死锁发生频繁的应用程序可能并不有效。

3 死锁的AND条件和OR条件

一般地,有两种死锁:资源死锁和通信死锁。在通信死锁中,进程等待的资源就是报文。资源死锁和通信死锁的真正区别在于资源死锁通常使用AND条件,而通信死锁通常使用OR条件。所谓AND条件就是当进程取得所有所需资源时,它才能继续执行;所谓OR条件就是当进程得到至少一个所需资源,它就能继续执行。由于多数分布式控制结构是不确定的,一个进程可能在等待来自多个进程的报文,而不能确定将被收到的报文究竟来自那个进程,需要每收到一个报文就进行处理,所以通信死锁使用OR条件。

在使用AND条件的系统中,死锁条件是在等待图中存在回路。但是在使用OR条件的系统中,等待图中的回路未必会引发死锁。在使用OR条件的系统中,死锁条件是存在结(knot)。

4 死锁的预防

死锁预防算法通过限制进程的资源请求方法来预防死锁。死锁预防通常通过下列方法之一来实现。它们都基于打破四个死锁条件中的一种:

1)静态分配资源。要求进程必须在开始执行前就申请它所需要的全部资源,并且只有当系统能满足进程的资源申请要求并把资源分配给进程之后,该进程才开始执行。这种策略可以预防死锁的发生是由于其破坏了“占有且等待资源”和“循环等待资源”的条件,从而系统中的所有进程必然不会发生死锁。

2)按序分配资源。在系统中的每一个资源都会给出一个编号。分配资源的时候作了以下规定:任何进程在申请两个以上资源时,总是按照编号的大小顺序申请。这种策略可以预防死锁的发生是由于其破坏了“循环等待资源”的条件,从而系统中的所有进程必然不会发生死锁。

3)剥夺式分配资源。当一个进程申请资源得不到满足时,可从另一个拥有这种资源的进程那里去抢夺,然后继续运行。这种策略可以预防死锁的发生是由于其破坏了“非抢夺式分配”的条件,从而系统中的所有进程必然不会发生死锁。

4.1 等待-死亡方案(Wait-die Scheme)

该方案是基于非剥夺方法。当进程Pi请求的资源正被进程Pj占有时,只有当Pi的时间戳比进程Pj的时间戳小时,即Pi比Pj老时,Pi才能等待。否则Pi被卷回(roll-back),即死亡。一个进程死亡后会释放他所占用的所有资源。在这里假定死亡的进程将带着同样的时间戳重新运行。由于具有较小时间戳的进程才等待具有较大时间戳的进程,因此很显然死锁不会发生。当进程在等待特定的资源时,不会释放资源。一旦一个进程释放一个资源,与这个资源相联系的等待队列中的一个进程将被激活。

4.2 伤害-等待方案(Wound-wait Scheme)

它是一种基于剥夺的方法。当进程Pi请求的资源正被进程Pj占有时,只有当进程Pi的时间戳比进程Pj的时间戳大时,即Pi比Pj年轻时,Pi才能等待。否则Pj被卷回(roll-back),即死亡。只要被卷回的进程重新启动时,使用原有的时间戳,这两种方案都能避免死锁和饿死现象。由于时间戳总是增加的,被卷回的进程最终将具有最小的时间戳。

5 死锁的检测

为了降低系统开销,在分配资源时会不加限制,只要系统中有剩余的资源,总是把资源分配给申请者。显然,这样的结果是可能会出现死锁。那么,为了使系统能够正常工作,在系统中会采用定时运行一个“死锁检测”程序的方法,当检测到死锁时该程序将会设法将其排除。在分布式系统中的死锁检测法不会造成很多不必要的进程流产,但是也会增加了系统的额外开销和复杂度。

5.1集中式死锁检测

在分布式系统中,每个站点都有一个本地死锁检测程序,其任务是判断在其站点所有潜在的全局死锁;其方法是:在站点的输入端口开始,沿本地等待图反向搜索,如果最终会搜索到输出端口,就说明具有潜在的全局死锁。

5.2分布式死锁检测

分布式死锁检测和集中式的主要差别是:在集中式方案中全部潜在的死锁循环都发送给某个指定的站点,而在分布式检测方案中则没有这种站点。分布式死锁检测机构中没有本地和非本地死锁检测程序的任何区别,每个站点具有同样的责任。在分布式方案中,死锁检测程序需要一种规则来决定应该把潜在的死锁循环发送给哪个站点,这种规则必须保证能最终检测到全局死锁,并且必须尽量减小传送的信息量。

Knapp将分布式死锁检测算法分为以下四类:

(1)路径推动算法(path-pushing algorithm)。先在每个机器上建立形式简单的全局等待图。每当进行死锁检测时,各个机器就将等待图的拷贝送往一定数量的邻居节点。局部拷贝更新后又被传播下去。这一过程重复进行直到某个节点获得了足够的信息来构造一个等待图以便做出是否存在死锁的结论。不幸的是,这类算法中的许多算法在实际中是错误的。主要原因是传输过程中的部分等待图并不能代表整个全局等待图,因为各个节点采集数据的方法是异步的。

(2)边跟踪算法(edge-chasing algorithm)。分布式网络结构图中的回路可以通过沿图的边传播一种叫探测器的特殊信息来检测。当一个发起者得到一个与自己发送的探测器相匹配的探测器时,它就知道它在图中的一个回路里。

(3)扩散计算(diffusing computation)。怀疑有死锁发生时,事务管理器通过向依赖于它的进程发送查询启动一个扩散进程。这里不会生成全局等待图。发送查询信息时,扩散计算就增长;接收回答后,扩散计算就缩减。根据所得信息,发起者会检测到死锁的发生。典型情况是,扩散进程动态地生成等待图的一个子树。

(4)全局状态检测(global state detection)。这个方法基于Chandy和Lamport 的快照方法。可以通过建立一个一致的全局状态而无需暂停当前的计算来生成一个一致的全局等待图。

你可能感兴趣的:(Linux)