What is a deadlock in multithreading? How can you prevent it?

A deadlock occurs when two or more threads each hold a lock the other needs and neither can proceed, so all involved threads block forever. It typically arises from multiple threads acquiring the same set of locks in inconsistent order.

Key Points: • Classic deadlock requires four conditions simultaneously: mutual exclusion, hold-and-wait, no preemption, and circular wait among the threads. • The most common prevention technique is enforcing a consistent global lock ordering, so every thread acquires multiple locks in the same sequence, eliminating circular wait. • Using tryLock() with a timeout, from java.util.concurrent.locks.Lock, lets a thread back off and retry instead of blocking indefinitely if it can't acquire a lock. • Minimizing the scope of locking, holding locks for the shortest time possible and avoiding calling unknown code while holding a lock, reduces the window for contention. • Higher-level concurrency utilities, like ConcurrentHashMap, java.util.concurrent executors, and atomic classes, avoid manual lock management entirely for many common cases, sidestepping deadlock risk altogether.

Example: Thread A locks account1 then tries to lock account2 for a transfer, while Thread B simultaneously locks account2 then tries to lock account1 — each thread now waits forever for a lock the other holds, which is fixed by always acquiring locks in a consistent order, such as by account ID.

Code Example:

Lock first = accountId1 < accountId2 ? lock1 : lock2;
Lock second = accountId1 < accountId2 ? lock2 : lock1;

first.lock();
try {
    second.lock();
    try {
        // transfer funds
    } finally {
        second.unlock();
    }
} finally {
    first.unlock();
}

Interview Tip: A concise interview answer is:

"A deadlock happens when threads each hold a lock the other needs, so both wait forever — classically caused by acquiring locks in inconsistent order. I prevent it by always acquiring locks in a fixed global order, keeping locked sections small, and using tryLock with a timeout so a thread can back off instead of blocking indefinitely."