public class WaitLockDrop { final Object lock1 = new Object(); final Object lock2 = new Object(); public void run() { Thread t1 = new Thread(new Runnable() { public void run() { synchronized(lock1) { synchronized(lock2) { try { lock2.wait(); // drops lock2, but not lock1 } catch(InterruptedException ie) { /* ignore */ } } } } }); Thread t2 = new Thread(new Runnable() { public void run() { try { Thread.sleep(1000); } catch(InterruptedException ie) { /* ignore */ } synchronized(lock1) { synchronized(lock2) { lock2.notify(); } } } }); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch(InterruptedException ie) { /* ignore */ } } public static void main(String[] args) { (new WaitLockDrop()).run(); } }