Bart van Heukelom
Bart van Heukelom

Reputation: 44124

How to avoid an easily made deadlock?

I have an object User with two locks, inventoryLock and currencyLock. Often these locks will be used individually, e.g.

synchronized (user.inventoryLock) {

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

}

or

synchronized (user.currencyLock) {

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

}

But sometimes a piece of code requires both locks:

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

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

 }
}

Seems simple, but there are more bits of code using both locks than just this example, and I know from previous experience that if multiple pieces of code require the same shared locks, they have a risk of deadlocking.

What's a good way to avoid that?

Is there maybe some kind of mechanism that will let me atomically lock on two objects?

Upvotes: 0

Views: 161

Answers (3)

blackcompe
blackcompe

Reputation: 3190

I don't see any circular wait possibilities here, which is 1 of 4 conditions necessary for deadlock.

Upvotes: 0

ratchet freak
ratchet freak

Reputation: 48226

always lock one lock before the other, one of the requirements of a deadlock is a circular waiting pattern

for example if you can ensure that you will always lock currencyLock before you lock inventoryLock and never attempt to lock currencyLock when you already have inventoryLock you will be fine

Upvotes: 3

Bart van Heukelom
Bart van Heukelom

Reputation: 44124

Just after posting this question I came up with a simple solution myself: Just make sure all the code acquires the locks in the same order. That way there can never be two thread both holding one of them.

If there is no natural order, alphabetical would suffice and be easy to remember.

Upvotes: 0

Related Questions