假设我有一个包含7个进程和3个资源A,B,C的系统。假设每个进程都需要读取&写一个{A,B,C}的不同非空子集,如何有效地防止死锁?即不能将3个资源上的互斥量整体放在一起。
答案 0 :(得分:4)
如果互斥锁支持非阻塞获取(通常称为trylock),则可以在没有锁定顺序/层次结构的情况下实现避免死锁的解决方案。算法如下:
通过非阻塞获取实现死锁避免(如果你已经拥有锁定,则永远等待锁定)和合作(成为一个好邻居并释放你已经获得的任何东西,如果你不能不阻止地继续)。
这种策略用于例如提升一次获取多个锁。实际上,在Boost中它更为先进:在步骤3释放锁定后,他们开始等待上一次尝试中忙碌的锁定。
另外,请查看以下SO主题:Acquire a lock on two mutexes and avoid deadlock,Multiple 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
现在每个进程都锁定了一个资源,正在等待另一个进程释放它所需的资源,从而导致死锁。