如何避免容易陷入僵局?

时间:2011-11-02 19:45:49

标签: java locking deadlock

我有一个具有两个锁的对象User,inventoryLock和currencyLock。这些锁通常会单独使用,例如

synchronized (user.inventoryLock) {

 // swap items
 tmp = user.inventory[x];
 user.inventory[x] = user.inventory[y];
 user.inventory[y] = tmp;

}

synchronized (user.currencyLock) {

 if (user.money < loss) throw new Exception();
 user.money -= loss;

}

但有时一段代码需要两个锁:

synchronized (user.currencyLock) {
 synchronized (user.inventoryLock) {

  if (user.money < item.price) throw new Exception();
  user.money -= item.price;
  user.inventory[empty] = item;

 }
}

看起来很简单,但是使用这两个锁的代码比这个例子还要多,而且我从以前的经验中知道,如果多个代码块需要相同的共享锁,那么它们就有死锁的风险。

避免这种情况的好方法是什么?

是否有某种机制可以让我原子地锁定两个对象?

3 个答案:

答案 0 :(得分:3)

总是先锁定另一个锁,其中一个死锁要求是循环等待模式

例如,如果您可以确保在锁定currencyLock之前始终锁定inventoryLock,并且在您已经拥有currencyLock时从不尝试锁定inventoryLock,那么您将没事

答案 1 :(得分:0)

在发布此问题之后,我自己想出了一个简单的解决方案:只需确保所有代码以相同的顺序获取锁定。这样就永远不会有两个线程同时持有其中一个。

如果没有自然顺序,按字母顺序排列就足够了,容易记住。

答案 2 :(得分:0)

我在这里看不到任何circular wait种可能性,这是死锁所需的4种情况之一。