我有一个具有两个锁的对象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;
}
}
看起来很简单,但是使用这两个锁的代码比这个例子还要多,而且我从以前的经验中知道,如果多个代码块需要相同的共享锁,那么它们就有死锁的风险。
避免这种情况的好方法是什么?
是否有某种机制可以让我原子地锁定两个对象?
答案 0 :(得分:3)
总是先锁定另一个锁,其中一个死锁要求是循环等待模式
例如,如果您可以确保在锁定currencyLock
之前始终锁定inventoryLock
,并且在您已经拥有currencyLock
时从不尝试锁定inventoryLock
,那么您将没事
答案 1 :(得分:0)
在发布此问题之后,我自己想出了一个简单的解决方案:只需确保所有代码以相同的顺序获取锁定。这样就永远不会有两个线程同时持有其中一个。
如果没有自然顺序,按字母顺序排列就足够了,容易记住。
答案 2 :(得分:0)
我在这里看不到任何circular wait种可能性,这是死锁所需的4种情况之一。