Thread Deadlock

About

Deadlock is a situation in multithreaded programming where two or more threads are waiting for each other's resources indefinitely, preventing any of them from proceeding. This results in a complete halt of execution for those threads.

Causes of Deadlock

These four conditions are known as the Coffman Conditions, and all must be true simultaneously for a deadlock to occur.

1. Circular Waiting

A set of threads are waiting on resources in a circular chain, where each thread holds a resource and waits for another that is held by the next thread in the chain.

Example:

  • Thread-1 holds Resource-A and waits for Resource-B.

  • Thread-2 holds Resource-B and waits for Resource-C.

  • Thread-3 holds Resource-C and waits for Resource-A.

Illustration of Circular Waiting:

Thread-1 → needs Resource-B → held by Thread-2
Thread-2 → needs Resource-C → held by Thread-3
Thread-3 → needs Resource-A → held by Thread-1
  • No thread can proceed, resulting in deadlock.

Solution:

  • Break the circular chain by acquiring locks in a specific order.

  • Example: Always acquire Resource-A before Resource-B.

2. Hold and Wait

A thread holds a resource and waits indefinitely for another resource, which may be held by another thread.

Example:

  • Thread-1 locks Resource-A and needs Resource-B.

  • Thread-2 locks Resource-B and needs Resource-A.

  • Neither thread can proceed, leading to deadlock.

Solution:

  • Avoid holding resources while waiting.

  • Use tryLock() instead of synchronization.

  • If both locks cannot be acquired, the thread releases any held lock and tries again, preventing deadlock.

3. No Preemption

A resource cannot be forcefully taken from a thread. A thread must release it voluntarily.

Example:

  • Thread-1 holds Resource-A and needs Resource-B.

  • Thread-2 holds Resource-B and needs Resource-A.

  • Neither can release resources, leading to deadlock.

Solution:

  • Use a timeout mechanism (tryLock() with timeout).

  • If a thread cannot get the required resource within a certain time, it releases the held resources and retries.

  • If a thread cannot acquire a lock within 2 seconds, it moves on instead of waiting indefinitely.

4. Mutual Exclusion

A resource can only be used by one thread at a time. If another thread needs it, it must wait.

Example:

  • Only one thread can access the method at a time, causing potential delays and deadlock risk.

Solution:

  • Minimize resource locking.

  • Use lock-free data structures (e.g., ConcurrentHashMap).

  • Implement fine-grained locking (lock only the required part of data).

Comparison of the Four Deadlock Conditions

Condition
Definition
Example
Solution

Circular Waiting

Threads wait in a cycle

A → B → C → A

Acquire locks in a fixed order

Hold and Wait

Holding resources while waiting for more

T1 locks A, waits for B

Use tryLock(), acquire all locks at once

No Preemption

Resources can't be forcefully taken

A locked by T1, B by T2

Use timeouts (tryLock(2, TimeUnit.SECONDS))

Mutual Exclusion

Only one thread can use a resource at a time

synchronizedmethods

Use lock-free data structures (ConcurrentHashMap)

Last updated