Engineering Full Stack Apps with Java and JavaScript
We have seen a dynamic lock ordering deadlock example previously.
One solution, according to suggestion from Java Concurrency in Practice, is to make use of System.identityHashCode to order objects. We can change the above program by introducing a method1 wrapper class that will send the objects in the correct order after checking its System.identityHashCode value. In a rare case, the values of System.identityHashCode may be same for both objects, and in this case we will use additional synchronization to make sure only one thread will call method1 and hence the order does not matter.
package deadlock;
public class DynamicLockOrderingSolution {
final static Object lockObject1 = new Object();
final static Object lockObject2 = new Object();
final static Object controlLock = new Object();
public static void method1Wrapper(Object obj1, Object obj2) {
int obj1Hash = System.identityHashCode(obj1);
int obj2Hash = System.identityHashCode(obj2);
if (obj1Hash < obj2Hash) {
method1(obj1, obj2);
} else if (obj1Hash > obj2Hash) {
method1(obj2, obj1);
} else {
synchronized (controlLock) {
method1(obj1, obj2);
}
}
}
public static void method1(Object obj1, Object obj2) {
synchronized (obj1) { // Locking on obj1
System.out.println(Thread.currentThread().getName()
+ ": Got obj1. Trying for obj2");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2) // Locking on obj2
{
System.out.println(Thread.currentThread().getName()
+ ": Got obj2.");
}
}
}
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
DynamicLockOrderingSolution.method1Wrapper(lockObject1, lockObject2);
}
};
t1.setName("Thread A");
t1.start();
Thread t2 = new Thread() {
public void run() {
DynamicLockOrderingSolution.method1Wrapper(lockObject2, lockObject1);
}
};
t2.setName("Thread B");
t2.start();
}
}
Just copy paste, execute, make changes and try to understand.
Java Concurrency in Practice by Brian Goetz, David Holmes, DOug Lea, Tim Peierls, Joshua Bloch and Joseph Bowbeer.