import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class TwoLocks { Lock locka = new ReentrantLock(); Lock lockb = new ReentrantLock(); // The safe way public void lock2(Lock a, Lock b) { if(System.identityHashCode(a) < System.identityHashCode(b)) { a.lock(); b.lock(); } else { b.lock(); a.lock(); } } public void method1a() { try { locka.lock(); lockb.lock(); System.out.println("method1a"); } finally { locka.unlock(); lockb.unlock(); } } public void method1b() { try { lockb.lock(); locka.lock(); System.out.println("method1b"); } finally { locka.unlock(); lockb.unlock(); } } public static void main(String[] args) throws InterruptedException { final int N = 100; final TwoLocks twoLocks = new TwoLocks(); boolean safe = false; Thread t1 = null; Thread t2 = null; if(safe) { // method2a and method2b ensure // that locks are obtained in the // same order. They do not deadlock. t1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < N; i++) { twoLocks.method2a(); } } }); t2 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < N; i++) { twoLocks.method2b(); } } }); } else { // method1a and method1b do not ensure // that locks are obtained in the // same order. They deadlock. t1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < N; i++) { twoLocks.method1a(); } } }); t2 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < N; i++) { twoLocks.method1b(); } } }); } t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("end"); } private void method2a() { try { lock2(locka, lockb); System.out.println("method2a"); } finally { locka.unlock(); lockb.unlock(); } } private void method2b() { try { lock2(lockb, locka); System.out.println("method2b"); } finally { locka.unlock(); lockb.unlock(); } } }