Card 02/ 08
All 8 cards
ExampleDifficulty: Intermediate1 min
A Transfer Between Two Accounts, Run in Both Directions at Once
A transfer method that locks both accounts before moving anything. It is correct, it is careful, and two of them running at once will stop the process dead.
void transfer(Account from, Account to, long pence) {
synchronized (from) {
synchronized (to) {
from.withdraw(pence);
to.deposit(pence);
}
}
}new Thread(() -> transfer(alice, bob, 100)).start();
new Thread(() -> transfer(bob, alice, 50)).start();The first thread takes Alice's lock and wants Bob's. The second takes Bob's and wants Alice's. Both are inside line 2 and stuck on line 3, and the accounts are locked for the rest of the process's life.
Neither thread did anything wrong. Each locked everything it needed before touching anything, which is the advice — and the advice is not enough on its own, because the two threads locked the same two objects in opposite orders.