复杂系统中的死锁预防

时间:2014-10-22 14:16:27

标签: multithreading concurrency deadlock

假设我有一个包含7个进程和3个资源A,B,C的系统。假设每个进程都需要读取&写一个{A,B,C}的不同非空子集,如何有效地防止死锁?即不能将3个资源上的互斥量整体放在一起。

3 个答案:

答案 0 :(得分:4)

如果互斥锁支持非阻塞获取(通常称为trylock),则可以在没有锁定顺序/层次结构的情况下实现避免死锁的解决方案。算法如下:

  1. 获取第一个资源的锁;在这里等待是允许的。
  2. 获得第一个锁后,尝试使用try-lock获取另一个锁。
  3. 如果try-lock失败(表示资源正忙),请释放所有先前获取的锁并转到步骤1.
  4. 如果尝试成功,请从步骤2开始重复所有剩余资源。
  5. 通过非阻塞获取实现死锁避免(如果你已经拥有锁定,则永远等待锁定)和合作(成为一个好邻居并释放你已经获得的任何东西,如果你不能不阻止地继续)。

    这种策略用于例如提升一次获取多个锁。实际上,在Boost中它更为先进:在步骤3释放锁定后,他们开始等待上一次尝试中忙碌的锁定。

    另外,请查看以下SO主题:Acquire a lock on two mutexes and avoid deadlockMultiple mutex locking strategies and why libraries don't use address comparison

答案 1 :(得分:2)

当我们将资源组织成某种层次结构时,通常会解决这些问题。您有三个资源{A, B, C},我们可以确定A位于层次结构的顶部,C位于底部。现在有两种方法:

悲观:如果我需要资源X,那么我还必须获得高于X的所有资源,即使此时我不需要它们。原因是我可能在其他时间需要它们,同时仍保留资源X

乐观:如果我需要资源X,那么就获得它。如果以后我需要资源X-below,那么也可以获得它,没问题。但是,如果X我需要资源X-above然后运气不好,我在持有资源X时无法获得它,但我可以释放资源X,然后首先获得X-above,然后再获得X

如果所有进程都遵循资源层次结构,那么就不会发生死锁。

答案 2 :(得分:1)

您需要决定获取资源的订单,然后始终以相同的顺序获取它们。

使用您的示例,应始终按照A,B,C的顺序获取资源。例如:

P1 => A
P2 => A C
P3 => C
P4 => B C
P5 => B
P6 => A B
P7 => A B C

这种方式永远不会出现所有进程都持有一个资源并等待另一个进程拥有的资源的情况。

在一个更简单的场景中:

P1 => A B
P2 => B C

这里两个进程都将获得他们的第一个资源,但进程P1将阻止,因为P2有B,但是,P2将能够获得C并将取得进展。在某些时候它将释放C,这将允许P1继续。

如果您没有按固定顺序获取它们,那么您可以获得以下内容:

P1 => A B
P2 => B A

现在每个进程都锁定了一个资源,正在等待另一个进程释放它所需的资源,从而导致死锁。