Java deadlock detection
Friday, 8. August 2008
Detecting deadlock is one of common features of Java profiling tools but I haven’t experienced the situation where those tools detect deadlock from code I wrote. In fact, deadlock is hazardous because it is difficult to predict and reproduce.
I wondered under what conditions do profilers detect deadlock and then report it, so I wrote code that reaches deadlock.
package com.grayger.deadlock;
public class SimpleDeadlocker {
private final static Object OBJ1=new Object();
private final static Object OBJ2=new Object();
private final static int LOOP=100;
public void obj1First() {
synchronized(OBJ1) {
printInfo("Hold OBJ1");
synchronized(OBJ2) {
printInfo("Hole OBJ2");
}
printInfo("Release OBJ2");
}
printInfo("Release OBJ1");
}
public void obj2First() {
synchronized(OBJ2) {
printInfo("Hold OBJ2");
synchronized(OBJ1) {
printInfo("Hole OBJ1");
}
printInfo("Release OBJ1");
}
printInfo("Release OBJ2");
}
private void printInfo(String info) {
System.out.println(Thread.currentThread().getName()+" "+info);
}
public static void main(String args[]) {
final SimpleDeadlocker d=new SimpleDeadlocker();
Thread t1=new Thread(new Runnable() {
public void run() {
for(int i=0;i<loop;i++)>
d.obj1First();
}
d.printInfo("Terminated");
}
}, "OBJ1_First");
Thread t2=new Thread(new Runnable() {
public void run() {
for(int i=0;i<loop;i++)>
d.obj2First();
}
d.printInfo("Terminated");
}
}, "OBJ2_First");
t1.start();
t2.start();
}
}
Above example can be refactored as follows:
package com.grayger.deadlock;
public class Deadlocker {
private final static int LOOP=100;
static class Deadlock1 {
private final static Object OBJ1=new Object();
private final static Object OBJ2=new Object();
public void obj1First() {
synchronized(OBJ1) {
printInfo("Hold OBJ1");
synchronized(OBJ2) {
printInfo("Hole OBJ2");
}
printInfo("Release OBJ2");
}
printInfo("Release OBJ1");
}
}
static class Deadlock2 {
private final static Object OBJ1=new Object();
private final static Object OBJ2=new Object();
public void obj2First() {
synchronized(OBJ2) {
printInfo("Hold OBJ2");
synchronized(OBJ1) {
printInfo("Hole OBJ1");
}
printInfo("Release OBJ1");
}
printInfo("Release OBJ2");
}
}
public static void printInfo(String info) {
System.out.println(Thread.currentThread().getName()+" "+info);
}
public static void main(String args[]) {
final Deadlock1 d1=new Deadlock1();
final Deadlock2 d2=new Deadlock2();
Thread t1=new Thread(new Runnable() {
public void run() {
for(int i=0;i<loop;i++)>
d1.obj1First();
}
Deadlocker.printInfo("Terminated");
}
}, "OBJ1_First");
Thread t2=new Thread(new Runnable() {
public void run() {
for(int i=0;i<loop;i++)>
d2.obj2First();
}
Deadlocker.printInfo("Terminated");
}
}, "OBJ2_First");
t1.start();
t2.start();
}
}
