How do you prevent or avoid deadlock? — Cracked Java
// Concurrency & Multithreading · Deadlock, Livelock & Starvation
SeniorTheoryBig TechGoogleAmazon

How do you prevent or avoid deadlock?

Prevent deadlock by breaking one of the four Coffman conditions — most often circular wait, via a consistent global lock-ordering. Where you cannot order locks, use timed tryLock to break hold-and-wait, and shrink critical sections so locks are held briefly.

1. Lock ordering (kills circular wait)

If every thread acquires locks in the same total order, no cycle can form. Derive a stable rank — a business ID, or System.identityHashCode as a fallback:

void transfer(Account from, Account to, long amount) {
    Account first  = from.id() < to.id() ? from : to;
    Account second = first == from ? to : from;
    synchronized (first.lock()) {
        synchronized (second.lock()) {
            from.debit(amount);
            to.credit(amount);
        }
    }
}

Handle the from.id() == to.id() self-transfer case (use a tie-breaker or reject it) so you do not deadlock on yourself.

2. tryLock with timeout (kills hold-and-wait)

When a global order is impractical, acquire locks optimistically and back off if you cannot get them all:

boolean transfer(Account a, Account b, long amount) throws InterruptedException {
    long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(200);
    while (System.nanoTime() < deadline) {
        if (a.lock().tryLock(50, TimeUnit.MILLISECONDS)) {
            try {
                if (b.lock().tryLock(50, TimeUnit.MILLISECONDS)) {
                    try { a.debit(amount); b.credit(amount); return true; }
                    finally { b.lock().unlock(); }
                }
            } finally { a.lock().unlock(); }
        }
        Thread.sleep(ThreadLocalRandom.current().nextInt(20)); // randomized backoff avoids livelock
    }
    return false;
}

The randomized backoff matters — fixed backoff turns a deadlock into a livelock where both threads retry in lockstep.

3. Open calls and smaller critical sections

An open call means invoking external/alien code (callbacks, other components) without holding a lock. Copy the data you need, release the lock, then make the call — alien code might try to grab a lock in the wrong order. Generally, hold locks for the shortest possible span and never block on I/O or await while holding one.

Mark your status