Initially: SharedData sd; boolean theCondition = false; Lock theLock = new Lock(); Condition AcanProceed = new Condition(theLock); Condition BcanProceed = new Condition(theLock); // Note here the same lock is used for both condition variables -- because // there is only one shared resource to protect. A's code: theLock.acquire(); while (!theCondition) { BcanProceed.wake(); AcanProceed.sleep(); // Releases the lock and go to sleep atomically. // And we will have the lock when we are waken up. } // Do something to sd ...... // Reset the flag. theCondition = false; // Wake up B BcanProceed.wake(); lock.release(); return; B's code: theLock.acquire(); while (theCondition) { AcanProceed.wake(); BcanProceed.sleep(); // Releases the lock and go to sleep atomically. // And we will have the lock when we are waken up. } // Do something to sd ...... // Reset the flag. theCondition = true; // Wake up A AcanProceed.wake(); lock.release(); return; Note: 1. Typically you need one condition variable for each condition in your program logic. 2. You may not need the flag at all times. Sometimes the simple fact that you are waken up by some thread is enough for you to proceed.