Friday, November 5, 2010

Simulating a ordering deadlock

One of the major drawbacks of the synchronized keyword is the deadlock scenario. If we need to acquire locks on two objects Object A and Object B simultaneously and then work on them , we need to make sure that the order of acquiring the lock is maintained. If the Lock on Object A is acquired first and then on B then the code can be considered safe and deadlock resistant. If on the other hand the order is not guaranteed then code has the potential of reaching a dead lock, as the following code demonstrates. The Transaction class has two methods transferA2B and transferB2A where the lock is acquired in two different orders. A sleep time of 1 sec is set after acquiring the lock in the first object in each method.

Transaction class


public class Transaction {
private Object accountA = new Object();
private Object accountB = new Object();
public void transferA2B(){
synchronized (accountA) {
System.out.println("lock for A held in A2B");
try { // sleep given to force deadlock
Thread.sleep(1000);
} catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();
}
synchronized (accountB) {
System.out.println("lock for B held in A2B");
}
}
}

public void transferB2A(){
synchronized (accountB) {
System.out.println("lock for B held in B2A");
try { // sleep given to force deadlock
Thread.sleep(1000);
} catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace();
} synchronized (accountA) {
System.out.println("lock for A held in B2A");
}
}
}
}

Two Threads A and B will call the individual methods of Transaction from the run method, so I am avoiding the code snippets for the threads

The DeadloackTest class


public class DeadlockTest {
public static void main(String[] args) {
Transaction tran = new Transaction();
Thread a = new Thread(new ThreadA(tran));
  Thread b = new Thread(new ThreadB(tran));  
a.start();  b.start(); 
}}

No comments:

Post a Comment