Card 06/ 08

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.

java
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.

What a timeout changes
Compared onWithout a timeoutWith one
The cycle formsYesYes
Threads recoverNeverAfter the timeout
The caller seesNothing, foreverA failure they have to handle
Under loadThe process stopsTransfers 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.