Card 06/ 08
All 8 cards
GotchaDifficulty: Advanced1 min
Why a Timeout Detects a Deadlock and Does Not Prevent One
Every lock is taken with a five-second timeout, so the service can no longer hang. It hangs less and now fails intermittently under load, and the cause is the same one.
if (fromLock.tryLock(5, SECONDS)) {
try {
if (toLock.tryLock(5, SECONDS)) {
try { move(pence); } finally { toLock.unlock(); }
} else {
throw new TransferTimedOut();
}
} finally { fromLock.unlock(); }
}The cycle still forms. Both threads take their first lock, both fail to get the second, and five seconds later both give up. What changed is what happens next — an exception instead of a hang.
| Compared on | Without a timeout | With one |
|---|---|---|
| The cycle forms | Yes | Yes |
| Threads recover | Never | After the timeout |
| The caller sees | Nothing, forever | A failure they have to handle |
| Under load | The process stops | Transfers fail intermittently |
So a timeout is a safety net and not a fix. Order the locks so the cycle cannot form, and keep the timeout for the case you did not think of.