获取多个锁时解决死锁

Solving Deadlock when acquiring Multiple Locks

例如,我有多个线程 T1、T2、T3 和 T4。 T1有资源A,T2有资源B,T3有资源A、B、C,T4有资源B、C。

当T1来的时候,它锁定A并做一些工作。

然后T2来了,它锁定了B并做了一些工作。

接下来是 T3,它锁定了 C 但正在等待 A(还没有 B,因为 A 尚未获得)。

终于到了T4,它等待B(还没有C,因为B还没有获得)。

伪代码如下:

for all resources needed {  // in case of T3, they are A and B
    acquire lock on resource;  // acquiring lock one after one
}

现在如果T2完成并释放B上的锁,T4被唤醒锁定B。但是它仍然需要等待C。所以现在T4持有B并等待C。

当T1完成并释放A的锁时发生死锁,T3被唤醒以锁定A。但它仍然需要等待B。T3现在持有A和C并等待B。然后我有T3 T4 进入无限等待。

为了解决这个问题,我的伪代码改为:

while not all resource locks obtained {  // in case of T3, they are A and B
    try to lock on resource;  // immediate return success or fail
    if fail, release all unsecured locks; // in case of T3, C is secured,
                                          // so only A and B may be released,
                                          // in case of T4, both B and C may be released
}

更改后的代码有效,但在我的测试中,我可以看到 T3 和 T4 不断检查锁,并且由于 while 循环,整个程序 运行 变慢了。

然后我对代码做了一个小改动:

while not all resource locks obtained {
    try for 1 second to lock on resource;  // return after 1 second if fail
    if fail, release all unsecured locks;
}

细微的变化使得锁检查的频率降低,程序 运行 比以前更快。

我不喜欢我目前拥有的东西,因为它似乎不是最佳的,而且效果有点 运行dom 在达到预期结果之前。有没有更好的方法来解决上面提到的死锁情况,还是我应该解决我现在的问题?

防止死锁很简单:

  1. 从不升级锁,例如将读锁升级为写锁
  2. 始终以相同顺序获取锁

你不是在做第二个。您只是随机尝试获取锁 - 当然这是低效的。

任何真正死锁的解决方案都是始终以相同的顺序获取锁。无需休眠或重试。