wait(), notify(), and notifyAll() in Java
Fast recall
Quick revision
Core answer
wait() makes the current thread release the receiver object's monitor and enter that object's wait set; it can return after notification, interruption, timeout, or a spurious wakeup, and must reacquire the monitor first. notify() selects one arbitrary waiter and notifyAll() wakes all current waiters to compete for that monitor. The caller must own the same monitor.Whether the candidate understands inter-thread communication and the monitor-based coordination model in Java.
Not knowing these must be called inside synchronized — will throw IllegalMonitorStateException at runtime.
Explain why wait() is always placed in a while loop instead of an if statement to guard against spurious wakeups.
Interview-ready guide
Interview answer
So wait, notify, and notifyAll are Java's built-in way for threads to coordinate.
They're all methods on the Object class. When you call wait, the current thread releases the monitor of the object on which wait() is called; any other held monitors remain owned and goes to sleep until someone calls notify or notifyAll on that same object. Here's the key part: you must call them inside a synchronized block or method.
If you don't, you'll get an IllegalMonitorStateException at runtime. Let's say you've got a shared queue. When it's full, the producer thread calls wait to pause itself and release the lock.
When a consumer removes an item, it calls notifyAll to wake up any producers that were waiting. The notified thread doesn't run right away though — it has to reacquire the lock first. That's why you always put wait inside a while loop, not an if statement.
Even after waking up, you need to recheck the condition because another thread might've gotten the lock first and changed things. One common mistake freshers make is using notify when they should use notifyAll. If you've got different types of threads waiting on the same object — like some waiting for space and others waiting for items — notify might wake the wrong one.
It's notifyAll is a common conservative choice when different conditions share a wait set, but every waiter still needs a correct condition loop. In production code, you'd usually use BlockingQueue instead of writing this yourself, but understanding wait and notify shows you know how Java's threading primitives actually work under the hood.
wait(), notify(), and notifyAll() in Java
Direct Answer
wait() makes the current thread release the receiver object's monitor and enter that object's wait set; it can return after notification, interruption, timeout, or a spurious wakeup, and must reacquire the monitor first. notify() selects one arbitrary waiter and notifyAll() wakes all current waiters to compete for that monitor. The caller must own the same monitor.
Code Example
import java.util.LinkedList;
import java.util.Queue;
class SharedBuffer {
private final Queue<String> queue = new LinkedList<>();
private final int capacity = 5;
public synchronized void produce(String item) throws InterruptedException {
while (queue.size() == capacity) {
wait(); // release lock and wait for space
}
queue.add(item);
System.out.println("Produced: " + item);
notifyAll(); // wake up waiting consumers
}
public synchronized String consume() throws InterruptedException {
while (queue.isEmpty()) {
wait(); // release lock and wait for items
}
var item = queue.poll();
System.out.println("Consumed: " + item);
notifyAll(); // wake up waiting producers
return item;
}
}
Common Mistakes & Pitfalls
- Calling wait outside synchronized: Freshers often call wait() or notify() without holding the monitor, which throws IllegalMonitorStateException at runtime. The JVM checks this at method entry.
- Using if instead of while: Checking the condition with if (queue.isEmpty()) wait(); instead of while looks correct but breaks with spurious wakeups or when multiple threads compete after notification — the condition might be false again by the time the thread runs.
- Calling notify on the wrong object: Each object has its own waiting set, so notifying a different object than the one waited on has no effect — the waiting thread never wakes up.
Check your understanding
Answer these without looking back at the article.
- Why must wait() be in a while loop instead of an if?
- What is a spurious wakeup?
- What is the difference between notify() and notifyAll()?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.