Deadlocks in Java

Deadlock describes a situation where two or more threads are blocked forever, waiting for each other.

Deadlock can occur when multiple threads need the same locks, at the same time but obtain them in different order.

For example, if a Thread thread1 locks A, and tries to lock B, and a thread thread2 has already locked B, and tries to lock A, a deadlock will arise. Thread1 can never get B, and Thread2 can never get A. They will remain blocked on each of their object’s which is A and B forever. This situation is called a deadlock.

Let’s see a simple example for the same

public class DeadLockExample {  
  public static void main(String[] args) {  
    String firstName = "James";  
    String secondName = "John";  
    //Now the thread th1 tries to lock firstName then secondName
    Thread th1 = new Thread() {  
      public void run() {  
          synchronized (firstName) {  
           System.out.println("Thread 1 is Running and has locked firstName");  
  
           try { 
                Thread.sleep(100);
           } 
           catch (Exception e) {
            System.out.println("Exception occured in thread 1 = "+e.getMessage())
           }  
  
           synchronized (secondName) {  
                 System.out.println("Thread 1 is Running and has locked secondName");  
           }  
         }  
      }  
    };  
  
    //Now the thread th2 tries to lock secondName then firstName
    Thread th2 = new Thread() {  
      public void run() {  
        synchronized (secondName) {  
          System.out.println("Thread 2 is Running and has locked secondName");  
  
          try { 
                Thread.sleep(100);
           } 
           catch (Exception e) {
            System.out.println("Exception occured in thread 2 = "+e.getMessage())
           }
  
          synchronized (firstName) {  
           System.out.println("Thread 2 is Running and has locked firstName");    
          }  
        }  
      }  
    };  
     
    th1.start();  
    th2.start();  
  }  
}  

O/P:

Output: Thread 1 is Running and has locked firstName
        Thread 2 is Running and has locked secondName

If you see the above program and check the output, thread 1 locked the firstName variable and thread 2 locked the secondName variable.

But thread 1 couldn’t lock the secondName variable because thread2 had locked it already and thread2 couldn’t lock the firstName variable because thread1 had locked it already.

So both the threads here would be blocked since they would be waiting for each other to release the locks and after a period of time fail due to deadlock error.

How to solve it:

The best way to solve would be to take the locks in a particular sequential order. Deadlock occurs when multiple threads need the same locks but obtain them in different order.If you make sure that all locks are always taken in the same order by any thread, deadlocks cannot occur.

Like for example, thread 2 instead tries to take a lock on firstName variable first and then secondName.

Doing this, the deadlock would be avoided.

public class DeadLockExample {  
  public static void main(String[] args) {  
    String firstName = "James";  
    String secondName = "John";  
    //Now the thread th1 tries to lock firstName then secondName
    Thread th1 = new Thread() {  
      public void run() {  
          synchronized (firstName) {  
           System.out.println("Thread 1 is Running and has locked firstName");  
  
           try { 
                Thread.sleep(100);
           } 
           catch (Exception e) {
            System.out.println("Exception occured in thread 1 = "+e.getMessage())
           }  
  
           synchronized (secondName) {  
                 System.out.println("Thread 1 is Running and has locked secondName");  
           }  
         }  
      }  
    };  
  
    //Now the thread th2 tries to lock firstName then secondName
    Thread th2 = new Thread() {  
      public void run() {  
        synchronized (firstName) {  
          System.out.println("Thread 2 is Running and has locked firstName");  
  
          try { 
                Thread.sleep(100);
           } 
           catch (Exception e) {
            System.out.println("Exception occured in thread 2 = "+e.getMessage())
           }
  
          synchronized (secondName) {  
           System.out.println("Thread 2 is Running and has locked secondName");    
          }  
        }  
      }  
    };  
     
    th1.start();  
    th2.start();  
  }  
}  

O/P:

Output: Thread 1 is Running and has locked firstName
        Thread 2 is Running and has locked firstName
        Thread 1 is Running and has locked secondName
        Thread 2 is Running and has locked secondName

Also, We should use locks only for those members on which it is required.

Thanks for reading!!!