What Is a Deadlock in Java and How Can You Prevent It?

Deadlock in Java is a condition where two or more threads are blocked forever, each waiting for the other to release a lock. This occurs primarily in a multithreaded environment when synchronized resources are used in such a way that a circular wait condition arises. Understanding and preventing deadlocks is crucial for building efficient and bug-free Java applications.


🔁 What Causes Deadlock in Java?

Deadlock occurs when the following four conditions are met simultaneously:

  1. Mutual Exclusion: At least one resource must be held in a non-shareable mode.
  2. Hold and Wait: A thread holding at least one resource is waiting to acquire additional resources held by other threads.
  3. No Preemption: Resources cannot be forcibly removed from threads holding them.
  4. Circular Wait: A set of threads are each waiting for a resource that the next thread in the cycle holds.

Note: All four conditions must be true for a deadlock to occur. Removing any one can prevent deadlock.


🧵 Java Deadlock Code Example

Let’s look at a simple code example that demonstrates a classic deadlock scenario:


class SharedResource {
    void methodA() {
        synchronized (String.class) {
            System.out.println(Thread.currentThread().getName() + " locked String.class");

            synchronized (Integer.class) {
                System.out.println(Thread.currentThread().getName() + " locked Integer.class");
            }
        }
    }

    void methodB() {
        synchronized (Integer.class) {
            System.out.println(Thread.currentThread().getName() + " locked Integer.class");

            synchronized (String.class) {
                System.out.println(Thread.currentThread().getName() + " locked String.class");
            }
        }
    }
}

public class DeadlockExample {
    public static void main(String[] args) {
        SharedResource resource = new SharedResource();

        Thread t1 = new Thread(() -> resource.methodA(), "Thread-1");
        Thread t2 = new Thread(() -> resource.methodB(), "Thread-2");

        t1.start();
        t2.start();
    }
}

In the code above:

  • Thread-1 locks String.class and waits for Integer.class.
  • Thread-2 locks Integer.class and waits for String.class.

This creates a circular wait and results in a deadlock.


⚠️ How to Detect Deadlocks in Java?

Deadlocks can be hard to detect manually. Java provides several tools:

  • jconsole – A Java monitoring tool.
  • jstack – Prints Java thread stack traces for a Java process.
  • VisualVM – Graphical interface to monitor JVM.

Using jstack:


jstack <pid> | grep -A 30 "Found one Java-level deadlock"

This command identifies deadlocked threads and shows the locks they are holding or waiting for.


💡 How to Prevent Deadlocks in Java?

Several techniques can help prevent deadlocks in Java:

1. Lock Ordering

Always acquire locks in a consistent global order.


synchronized (String.class) {
    synchronized (Integer.class) {
        // do something
    }
}

Ensure that all threads follow this same lock order.

2. Try-Lock with Timeout

Use ReentrantLock.tryLock() with timeout to avoid indefinite waiting.


import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;

public class TryLockExample {
    private static ReentrantLock lock1 = new ReentrantLock();
    private static ReentrantLock lock2 = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            try {
                if (lock1.tryLock(1, TimeUnit.SECONDS)) {
                    Thread.sleep(500);
                    if (lock2.tryLock(1, TimeUnit.SECONDS)) {
                        System.out.println("Thread 1 acquired both locks");
                        lock2.unlock();
                    }
                    lock1.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread t2 = new Thread(() -> {
            try {
                if (lock2.tryLock(1, TimeUnit.SECONDS)) {
                    Thread.sleep(500);
                    if (lock1.tryLock(1, TimeUnit.SECONDS)) {
                        System.out.println("Thread 2 acquired both locks");
                        lock1.unlock();
                    }
                    lock2.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();
        t2.start();
    }
}

This technique prevents deadlock by avoiding waiting forever for a lock.

3. Avoid Nested Locks

Minimize the use of nested synchronized blocks. If not necessary, don’t acquire multiple locks simultaneously.

4. Use Higher-Level Concurrency Utilities

Prefer classes from java.util.concurrent like Semaphore, ExecutorService, etc., which provide better control and abstraction.


📊 Real-World Scenario Example

Let’s simulate a banking scenario where deadlock may occur if accounts try to transfer money simultaneously:


class Account {
    private int balance = 1000;

    public void withdraw(int amount) {
        balance -= amount;
    }

    public void deposit(int amount) {
        balance += amount;
    }

    public int getBalance() {
        return balance;
    }
}

class Transfer {
    public void transferMoney(Account from, Account to, int amount) {
        synchronized (from) {
            synchronized (to) {
                from.withdraw(amount);
                to.deposit(amount);
            }
        }
    }
}

public class BankDeadlock {
    public static void main(String[] args) {
        Account acc1 = new Account();
        Account acc2 = new Account();

        Transfer transfer = new Transfer();

        Thread t1 = new Thread(() -> transfer.transferMoney(acc1, acc2, 100));
        Thread t2 = new Thread(() -> transfer.transferMoney(acc2, acc1, 200));

        t1.start();
        t2.start();
    }
}

This program might deadlock because t

Please follow and like us:

8 thoughts on “What Is a Deadlock in Java and How Can You Prevent It?”

  1. We’re a gaggle of volunteers and starting a new scheme in our community. Your website offered us with helpful info to work on. You’ve done an impressive job and our whole group will probably be thankful to you.

    Reply

Leave a Comment