What is a Condition and how does it improve on wait/notify? — Cracked Java
SeniorTheory

What is a Condition and how does it improve on wait/notify?

A Condition is the explicit-lock equivalent of wait/notify/notifyAll, obtained from a Lock via newCondition(). Its decisive advantage: a single lock can have multiple Condition objects — multiple independent wait-sets — whereas an intrinsic monitor has exactly one. That lets you signal precisely the threads waiting on a specific predicate.

The bounded-buffer pattern

A classic producer/consumer needs two wait conditions: "buffer not full" for producers and "buffer not empty" for consumers. With synchronized you have one wait-set and must notifyAll(), waking everyone. With two Conditions you wake only the relevant group.

private final ReentrantLock lock = new ReentrantLock();
private final Condition notFull  = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private final Object[] items = new Object[100];
private int count, putIdx, takeIdx;

public void put(Object x) throws InterruptedException {
    lock.lock();
    try {
        while (count == items.length)
            notFull.await();           // releases lock, parks; re-acquires on wake
        items[putIdx] = x;
        putIdx = (putIdx + 1) % items.length;
        count++;
        notEmpty.signal();             // wake ONE consumer, not all
    } finally {
        lock.unlock();
    }
}

How it improves on wait/notify

  • Multiple wait-sets per lock — targeted signalling instead of waking unrelated threads (the "thundering herd" of notifyAll).
  • signal() is safe here because each Condition holds only threads waiting on the same predicate, so waking one is correct (unlike single-monitor notify(), which can wake the wrong waiter).
  • Richer waitingawaitNanos, await(time, unit), awaitUntil(deadline), and awaitUninterruptibly().

The rules carry over

You must hold the lock to call await/signal (else IllegalMonitorStateException). And always wait in a while loop, never an if — spurious wakeups exist, and even after a valid signal another thread may have changed the state before you re-acquire the lock. await() atomically releases the lock and re-acquires it on return.

Mark your status