public class WaitNotifySplitDemo { Object _lock = new Object(); volatile boolean _flag = false; void sleep(long millis) { try { Thread.sleep(millis); } catch(InterruptedException ie) { /* ignore */ } } class WaitRunnable implements Runnable { public void run() { sleep(1000); while(true) { // comment this and the } below back in to execute the _flag check and the wait // in the same synchronized block //synchronized(_lock) { // must own _lock before we can notify synchronized(_lock) { if (_flag) { break; } } sleep(50); // here we have broken apart the synchronized statement inti two parts synchronized(_lock) { try { _lock.wait(); } catch(InterruptedException ie) { /* ignore */ } } // comment this and synchronized(_lock) above back in to execute the _flag check and the wait // in the same synchronized block //} } } } class NotifyRunnable implements Runnable { public void run() { sleep(1000); // must own _lock before we can notify synchronized(_lock) { _flag = true; _lock.notifyAll(); // too early } } } final int NUM_THREADS = 10; void run() { Thread tN = new Thread(new NotifyRunnable()); Thread[] tW = new Thread[NUM_THREADS]; for(int i=0; i