Deadlock in Java with Example

We know that when more than one threads are used in a program, they share resources. At a time, a particular resource is allotted to a thread that gains object lock for that resource.

Deadlock in Java is a situation that occurs when a thread is waiting for an object lock, that is acquired by another thread, and second thread is waiting for an object lock that is acquired by the first thread.

Since both threads are waiting for each other to release the lock simultaneously, this condition is called deadlock in Java. The object locks acquired by both threads are not released until their execution is not completed.

Let’s understand it with an example. Look at the below figure where two threads are in a deadlock.

Deadlock condition in Java with Example

Suppose that thread1 and thread2 are two threads that are in a deadlock. The thread thread1 holds the lock for the resource R1 and waits for resource R2 that is acquired by thread thread2.

At the same time, thread thread2 holds the lock for the resource R2 and waits for R1 resource that is acquired by thread thread1. But thread2 cannot release the lock for resource R2 until it gets hold of resource R1.


Since both threads are waiting for each other to unlock resources R1 and R2, therefore, these mutually exclusive conditions are called deadlock in Java.

Let’s understand the concepts of deadlock with realtime examples.

Realtime Example of Deadlock in Java


A simple real-time example of deadlock is that suppose there are two friends John and Jerry that are drawing a diagram. During drawing, John needs an eraser, so he will use (lock) the eraser.

Meanwhile, Jerry needs ruler, so he will use (lock) the ruler. Currently, eraser and ruler are not occupied by any of the friends. Now John needs a ruler to continue his drawing. But Jerry will not give it because he is using it currently.

Later on, Jerry needs an eraser but John will not give it as his drawing is not completed because of waiting for the ruler. Thus, none of the friends will release stationary objects and both will wait infinitely for each other to release stationary. This situation is called deadlock in Java.

Similarly, assume that there are two threads t1 and t2. Both threads are running concurrently (simultaneously). During execution, thread t1 is waiting for data that is locked by thread t2 and t2 is waiting for data that is locked by thread t1.

In this case, none of the threads will unlock the lock because of not completing their execution process. This situation is called deadlock.

When thread deadlock occurs in a program, the further execution of program will stop. Therefore, thread deadlock is a drawback in a program. We should take care to avoid deadlock while coding.


Let’s take an example program to demonstrate deadlock.

Program code:

public class X {
void display1(X obj2)
{
   System.out.println("Thread1 waiting for thread2 to release lock");
   synchronized(obj2) {
      System.out.println("Deadlock occurred"); 
   }
}
void display2(X obj1)
{
   System.out.println("Thread2 waiting for thread1 to release lock");
   synchronized(obj1){
       System.out.println("Deadlock occurred"); 
   }
 } 
}
public class Thread1 extends Thread
{
   X obj1, obj2;
   Thread1(X obj1, X obj2)
   {
     this.obj1 = obj1;
     this.obj2 = obj2;
   }
public void run()
{
   synchronized(obj1){
   try {
      Thread.sleep(1000);  
   }
   catch(InterruptedException ie) {
      System.out.println(ie);	
   }
   obj2.display2(obj2);  
  }
}
}
public class Thread2 extends Thread 
{
   X obj1, obj2;
   Thread2(X obj1, X obj2)
   {
      this.obj1 = obj1;
      this.obj2 = obj2;
   }
   public void run()
   {
     synchronized(obj2){
     try {
       Thread.sleep(1000);  
     }
     catch(InterruptedException ie) {
         System.out.println(ie);	
     }
    obj1.display1(obj1);
  }
 }
}
public class Deadlock {
public static void main(String[] args) 
{
   X obj1 = new X();
   X obj2 = new X();

   Thread1 t1 = new Thread1(obj1, obj2);
   Thread2 t2 = new Thread2(obj1, obj2);
   t1.start();
   t2.start();
 }
}
Output:
       Thread1 waiting for thread2 to release lock
       Thread2 waiting for thread1 to release lock

Explanation:

1. First, Thread thread1 starts its execution and synchronizes on the object obj1 that prevents another thread to call method display1 on obj1 reference variable. Thread thread1 then goes to sleep by calling sleep() method and allows Thread thread2 to start its execution.

2. Now Thread thread2 starts its execution and synchronizes on the object reference obj2. It prevents display2() method on the object obj2 to be called by another thread. Thread thread2 goes to sleep by calling sleep() method and allows Thread thread1 to wake up.

3. Thread thread1 continues its execution and tries to call display2() method on obj2. But it cannot call this method on obj2 until the code inside Thread thread2 completes execution.

4. Since Thread thread1 cannot proceed its execution, Thread thread2 gets the control and tries to call display1() method on obj1 which is also not possible until the code inside Thread thread1 completes execution. Thus, neither of threads can continue their execution because they are deadlocked.

What are the conditions for deadlock in a program?


Deadlock in a program may occur due to the following conditions. They are as follows:

1. Mutual Exclusion: There is at least one resource that must be held in a non-sharable mode and hence, can be used only by one thread. If another thread requests for it, it should wait until the resource is available.

2. Hold and Wait: This condition occurs when one thread holds a resource and waits for another resource that is held by another thread.

3. No Preemption: The resource will be released only after the execution of thread is completed.

4. Circular Wait: This condition occurs when each thread is waiting for a resource held by the preceding one and the last thread is waiting for a resource held by first thread.

This is called circular wait deadlock. This is because every thread is waiting for a resource held by the next one and the last thread is waiting for a resource held by first.

How to Avoid Deadlock in Java Program?


There is no precise solution to overcome the problem of deadlock in a program. It depends on the logic used by the programmer. The programmer should create his program in such a way that it does not form the problem of deadlock.

A deadlock in a program can be prevented if any of the four conditions are not met. They are:

1. Mutual Exclusive Condition: If every resource is shared by multiple threads, deadlock would never occur.

2. Hold and Wait Condition: This condition can be eliminated when a thread is prohibited to wait for more resources while already holding a certain resource. It can be achieved when we declare all resources at the very beginning that are expected to use by a thread.

3. No Preemption Condition: This condition can be eliminated if a thread holding a certain resource is denied for further request. That thread must unlock its original resource. If necessary, request them again together with additional resource.

4. Circular Wait Condition: This is the easiest way to avoid deadlock than the above three. There are two ways to eliminate deadlock.

First way: It can be achieved if a thread is to force to hold only one resource at a time. If it needs another resource, it must first release that resource that is held by it and then requests another.

Second way: It can be achieved by acquiring resources (locks) in a specific order and releasing them in reverse order so that a thread can only continue to acquire a resource if it held the other one.


In this tutorial, we have explained the basic concepts of deadlock in Java with realtime example and program. We hope that you will have understood this topic and enjoy it. In the next, we will learn synchronized block in Java through examples.
Thanks for reading!!!

⇐ Prev Next ⇒

Please share your love