Example of deadlock in Java Multi-threading

When two threads or processes are waiting for each other to release the resource or object they hold and so are blocked forever. This situation is called “deadlock”. For example, if one thread is holding the lock on some object that the other thread is waiting for and the other thread is holding lock on some object the first one is waiting for then they both will wait for each other to release the object they need to finish their operation but no one will release the held object and so they will wait for each other forever.

DeadLock In MultiThreading

Example to show DeadLock condition

In this example, there are two thread objects myThread and yourThread. When myThread starts running it holds a lock on the str1 object. If now yourThread starts it gets a lock on str2. Now when first thread continues and wants a lock on str2 then it is not available because second thread already holds a lock on str2. Now both thread will wait for each other. myThread waits for str2 to be released by yourThread and yourThread is waiting for str1 to be released by myThread. This program now goes to the deadlock condition. Now if you want to break the program then you need to press CTRL and C from the keyboard.

Example

import java.util.*;
public class DeadLockDemo extends Thread {
 public static String str1 = "str1";
 public static String str2 = "str2";

public static void main(String[] a) {
 Thread myThread = new MyThread();
 Thread yourThread = new YourThread();

myThread.start();
 yourThread.start();
 }
 private static class MyThread extends Thread {
 public void run() {
 synchronized (str1) {
 System.out.println("MyThread Holds lock on object str1");
 try {
 Thread.sleep(10);
 }
 catch (InterruptedException e) {
 }
 
 System.out.println("MyThread waiting for lock on object str2");
 synchronized (str2) {
 System.out.println("MyThread Holds lock on objects str1, str2");
 }
 }
 }
 }
 private static class YourThread extends Thread {
 public void run() {
 synchronized (str2) {
 System.out.println("YourThread Holds lock on object str2");
 try {
 Thread.sleep(10);
 }
 catch (InterruptedException e) {}
 System.out.println("YourThread waiting for lock on object str1");
 synchronized (str1) {
 System.out.println("YourThread Holds lock on objects str1, str2");
 }
 }
 }
 }
}

Output

MyThread Holds lock on object str1
YourThread Holds lock on object str2
MyThread waiting for lock on object str2
YourThread waiting for lock on object str1

How to avoid Deadlock in Java?

The problem discussed above can be avoided by applying a suitable deadlock prevention technique. Following are some techniques available that can help to avoid the deadlock problem:

  • Non-Overlapping Locks: Avoid giving locks to multiple threads if it is already given to one
  • Using thread join: Deadlock condition occurs when one thread is waiting for the other to finish. If this condition is seen we can use Thread.join with maximum time you think the execution will take
  • Lock Ordering: We can prevent deadlocks by always obtain locks in a constant, predefined, order. For example, I need to obtain two locks lock-1 and lock-2. If lock-1 is always acquired before lock-2, then we can never have a deadlock, as the second thread will never have locks required by the first thread.
  • Single Thread: There are cases where deadlocks are unavoidable if multiple threads are used, such as handling of events within a GUI application. So, there is no other option but to have just a single thread handling all events.