Description

Wikipedia aptly defines deadlock is a situation in which two or more competing actions are each waiting for the other to finish, and thus neither ever does. If deadlock happens in a JVM, the only way to recover from the situation is to restart the JVM.

Example

Here is a sample code which simulates deadlock condition in-between two threads:

package com.tier1app;

public class DeadLockSimulator {
	
	   public static Object Lock1 = new Object();
	   public static Object Lock2 = new Object();

	   
	   private static class FirstThread extends Thread {
	      public void run() {
	         synchronized (Lock1) {
	            System.out.println("Thread 1: Holding lock 1...");
	            try { Thread.sleep(10); } catch (Exception e) {}
	            System.out.println("Thread 1: Waiting for lock 2...");
	            synchronized (Lock2) {
	               System.out.println("Thread 1: Holding lock 1 & 2...");
	            }
	         }
	      }
	   }
	   
	   private static class SecondThread extends Thread {
	      public void run() {
	         synchronized (Lock2) {
	            System.out.println("Thread 2: Holding lock 2...");
	            try { Thread.sleep(10); } catch (Exception e) {}
	            System.out.println("Thread 2: Waiting for lock 1...");
	            synchronized (Lock1) {
	               System.out.println("Thread 2: Holding lock 1 & 2...");
	            }
	         }
	      }
	   }
	
	public static void main(String args[]) {
		
		new FirstThread().start();
		new SecondThread().start();
	}
}

In the above code following is the execution path of ‘FirstThread‘:

1. Acquires lock on the Lock1 object
2. Sleeps for 10 seconds interval
3. Acquires lock on Lock2 object

Following is the execution path of ‘SecondThread‘:

1. Acquires lock on the Lock2 object
2. Sleeps for 10 seconds interval
3. Acquires lock on Lock1 object

If you read the above execution path carefully, FirstThread after executing step #1, it would have moved on to step #2. When it is in step #2, SecondThread would have executed it’s step #1. So by the time FirstThread wakes up and executes it’s step #3 (i.e. trying to acquire Lock2), SecondThread would have already acquired lock on Lock2. Similarly, SecondThread executes it’s step #3 (i.e. trying to acquire Lock1), FirstThread has already acquired lock on Lock1. Thus it results in classic deadlock situation. The only way to recover from this situation is to restart the JVM.

Thread dump captured on the above code would look like:

"Thread-1" prio=6 tid=0x0000000007319000 nid=0x7cd3c waiting for monitor entry [0x0000000008a3f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.tier1app.DeadLockSimulator$SecondThread.run(DeadLockSimulator.java:29)
	- waiting to lock 0x00000007ac3b1970 (a java.lang.Object)
	- locked 0x00000007ac3b1980 (a java.lang.Object)

   Locked ownable synchronizers:
	- None

"Thread-0" prio=6 tid=0x0000000007318800 nid=0x7da14 waiting for monitor entry [0x000000000883f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
	at com.tier1app.DeadLockSimulator$FirstThread.run(DeadLockSimulator.java:16)
	- waiting to lock 0x00000007ac3b1980 (a java.lang.Object)
	- locked 0x00000007ac3b1970 (a java.lang.Object)

   Locked ownable synchronizers:
	- None
Advertisements