获取多个锁时解决死锁问题

时间:2017-09-19 09:37:18

标签: java multithreading concurrency locking deadlock

我有多个线程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;
}

轻微的改变使锁定检查的频率降低,程序运行速度比以前快。

我不喜欢我现在所拥有的东西,因为它似乎不是最佳的,并且在达到预期效果之前效果是随机的。有没有更好的方法来解决上面提到的僵局情况,还是我应该解决现在的问题?

2 个答案:

答案 0 :(得分:2)

防止死锁很简单:

  1. 永远不要升级锁,例如将读锁升级为写锁
  2. 始终以相同的顺序获取锁
  3. 你没有做第二次。你只是随意地试图获取锁 - 当然这是低效的。

答案 1 :(得分:1)

任何真正的死锁的解决方案是始终以相同的顺序获取锁。不需要睡觉或重试。