Program/Code to Create Deadlock Between Two Threads in Java

Deadlock comes under topic Concurrency. I have already shared the Multithreading interview questions and answers here. I have recently given a few java interviews, where I faced the question program to create deadlock between two threads in java twice. Make sure this question is in your to do list, especially if you are going to interview for investment banks like Goldman Sachs, Bank of America,Morgan Stanley etc.Enough about the interview and let's first understand what is Deadlock.  

Read Also : Difference between Runnable and Callable in Java

What is Deadlock ?

According to Deadlock Oracle docs,

Deadlock describes a situation where two or more threads are blocked forever, waiting for each other.
When synchronized keyword in java causes the executing thread to block while waiting for the monitor(lock) associated with the specified object,then Deadlock may occur. Since the executing thread might already holds the object which is required by another thread (also in waiting state). In such a case, two threads end up waiting forever for each other object lock.




Deadlock in java



Program/Code to Create Deadlock between Two Threads in Java

public class DeadLockProgram {
    // Creating Object Locks
    static Object ObjectLock1 = new Object();
    static Object ObjectLock2 = new Object();
   
    private static class ThreadName1 extends Thread {
      public void run() {
         synchronized (ObjectLock1) {
            System.out.println("Thread 1: Has  ObjectLock1");
            /* Adding sleep() method so that
               Thread 2 can lock ObjectLock2 */
            try { 
                Thread.sleep(100);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 1: Waiting for ObjectLock 2");
            /*Thread 1 has ObjectLock1 
              but waiting for ObjectLock2*/
            synchronized (ObjectLock2) {
               System.out.println("Thread 1: No DeadLock");
            }
         }
      }
   }
   private static class ThreadName2 extends Thread {
      public void run() {
         synchronized (ObjectLock2) {
            System.out.println("Thread 2: Has  ObjectLock2");
            /* Adding sleep() method so that
               Thread 1 can lock ObjectLock1 */
            try { 
                Thread.sleep(100);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 2: Waiting for ObjectLock 1");
            /*Thread 2 has ObjectLock2 
              but waiting for ObjectLock1*/
            synchronized (ObjectLock1) {
               System.out.println("Thread 2: No DeadLock");
            }
         }
      }
   }
   
   public static void main(String args[]) {
      ThreadName1 thread1 = new ThreadName1();
      ThreadName2 thread2 = new ThreadName2();
      thread1.start();
      thread2.start();
   }
}

Output :
Thread 1: Has  ObjectLock1
Thread 2: Has  ObjectLock2
Thread 1: Waiting for ObjectLock 2
Thread 2: Waiting for ObjectLock 1
 

After executing above program you will find the situation of Deadlock as Thread1 waits for ObjectLock2 and Thread2 waits for ObjectLock1.Both threads keep on waiting forever.

How to Avoid Deadlock

The solution to avoid Deadlock is to reshuffle the pattern in which we are accessing the object locks ObjectLock1 and ObjectLock2. In other words, just reverse the order in which we are passing the ObjectLock1 and ObjectLock2 either in ThreadName1 class or ThreadName2 class but not in both. Let's try reshuffling in the above code and see whether we still get the Deadlock or not.

public class DeadLockProgram {
    // Creating Object Locks
    static Object ObjectLock1 = new Object();
    static Object ObjectLock2 = new Object();
   
    private static class ThreadName1 extends Thread {
      public void run() {
         synchronized (ObjectLock2) {
            System.out.println("Thread 1: Has  ObjectLock1");
            /* Adding sleep() method so that
               Thread 2 can lock ObjectLock2 */
            try { 
                Thread.sleep(100);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 1: Waiting for ObjectLock 2");
            /*Thread 1 has ObjectLock1 
              but waiting for ObjectLock2*/
            synchronized (ObjectLock1) {
               System.out.println("Thread 1: No DeadLock");
            }
         }
      }
   }
   private static class ThreadName2 extends Thread {
      public void run() {
         synchronized (ObjectLock2) {
            System.out.println("Thread 2: Has  ObjectLock2");
            /* Adding sleep() method so that
               Thread 1 can lock ObjectLock1 */
            try { 
                Thread.sleep(100);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread 2: Waiting for ObjectLock 1");
            /*Thread 2 has ObjectLock2 
              but waiting for ObjectLock1*/
            synchronized (ObjectLock1) {
               System.out.println("Thread 2: No DeadLock");
            }
         }
      }
   }
   
   public static void main(String args[]) {
      ThreadName1 thread1 = new ThreadName1();
      ThreadName2 thread2 = new ThreadName2();
      thread1.start();
      thread2.start();
   }
}

Output :
Thread 1: Has  ObjectLock1
Thread 1: Waiting for ObjectLock 2
Thread 1: No DeadLock
Thread 2: Has  ObjectLock2
Thread 2: Waiting for ObjectLock 1
Thread 2: No DeadLock


As you can see in the above output that we do not get the Deadlock. Both threads Thread1 and Thread2 finish executing their task.

Best Practices to Avoid Deadlock

1. Avoiding Nested Locks :

This is one of the most common reason to get the Deadlock. If you share the locks with multiple threads, then Deadlock might occur.Try to avoid sharing locks to multiple threads.

2. Avoiding Unnecessary Locks :

We should use lock when required. Unnecessary and frequent use of locks can lead to Deadlock which is fatal for the application.
 
Please mention in comments if you have any questions regarding deadlock.

About The Author

Subham Mittal has worked in Oracle for 3 years .
For more java articles ,Click here to Subscribe JavaHungry