如何避免容易造成的僵局



我有一个对象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;
 }
}

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

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

是否有某种机制可以让我自动锁定两个对象?

总是先锁一个锁再锁另一个锁,死锁的要求之一是循环等待模式

例如

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

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

如果没有自然顺序,按字母顺序排列就足够了,这样便于记忆。

我在这里没有看到任何循环等待的可能性,这是死锁所必需的4个条件之一。

最新更新