我有一个对象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个条件之一。