← Back to Java

notify() vs notifyAll()

JavaSeniorjava

The Question

What is the difference between notify() and notifyAll() in Java?

What a Strong Answer Covers

  • notify() wakes one waiting thread arbitrary
  • notifyAll() wakes all waiting threads
  • notify() can cause starvation
  • notifyAll() safer for multiple conditions
  • both require synchronized context

Senior-Level Answer

Both notify() and notifyAll() are Object methods that wake threads suspended in wait() on the same object's monitor. The critical difference is how many threads they wake.

notify() wakes exactly one thread from the wait set. The JVM chooses which thread arbitrarily — there is no fairness guarantee. The notified thread does not immediately execute; it must re-acquire the monitor lock (competing with all other threads that want it), then re-check its condition before proceeding.

notifyAll() wakes all threads in the wait set. They all compete to re-acquire the monitor. One wins, re-checks its condition, proceeds if satisfied, releases the lock. The others proceed one at a time in an undefined order, each re-checking its condition.

notify() is safe only when two strict conditions hold: (1) all waiting threads are identical — they wait on the same condition and perform the same action upon waking, and (2) only one thread needs to be activated per notification. If different threads wait on different conditions (e.g., some threads wait for 'buffer not full' and others for 'buffer not empty'), notify() may wake the wrong type of thread, which re-evaluates its condition, finds it unsatisfied, and calls wait() again — while the thread that should have been notified never wakes up. This is the classic missed wakeup / deadlock scenario.

notifyAll() is the safe default. The cost is thundering herd: many threads wake, compete for the lock, find their condition unsatisfied, and go back to sleep. For performance-critical code with many waiting threads and high throughput, this can be measurable.

The modern solution is java.util.concurrent.locks.Condition, which supports multiple condition queues per lock. In a producer-consumer pattern, you maintain a notFull and notEmpty Condition separately — signal() on notFull wakes only producer threads, signal() on notEmpty wakes only consumer threads. This gives the precision of notify() without the correctness risk.

Key Differences

Aspectnotify()notifyAll()
Threads wokenOne (arbitrary)All in the wait set
CorrectnessOnly safe if all waiters are identicalSafe in all cases
RiskMissed wakeup if wrong thread chosenThundering herd (performance)
PerformanceLower overhead, one wakeHigher overhead with many waiters
When to useSingle-condition wait set, identical waitersMultiple conditions or heterogeneous waiters
Modern alternativeCondition.signal()Condition.signalAll()

What Separates a 2/3 from a 3/3

2/3 — Passing but Incomplete

Correctly states notify() wakes one thread arbitrarily and notifyAll() wakes all, and identifies the missed wakeup risk with notify() when waiters have different conditions.

3/3 — Strong Answer

Explains the two conditions under which notify() is safe, describes the thundering herd issue with notifyAll(), and mentions Condition.signal()/signalAll() as the modern solution with separate wait queues.

Common Mistakes

  • Saying notify() wakes the 'next' or 'first' waiting thread — it wakes an arbitrary thread with no ordering guarantee.
  • Recommending notify() as a performance optimization without knowing the conditions that make it safe — this is a common source of threading bugs.
  • Not knowing about java.util.concurrent.locks.Condition as the proper way to have multiple wait queues on a single lock.

Follow-Up Questions

  • Describe a scenario where using notify() instead of notifyAll() causes a program to hang. — Producer-consumer with multiple condition types: a producer calls notify() when adding an item, but wakes another producer (waiting for space) instead of a waiting consumer — the consumer never wakes and the buffer fills, deadlocking.
  • How do Condition objects from java.util.concurrent.locks.Lock solve the notify() problem? — A Lock can have multiple Condition objects (notFull, notEmpty). Producers await on notFull and signal notEmpty; consumers do the reverse — perfect targeting without notifyAll() overhead.
  • After notifyAll() wakes all threads, what happens if all re-check their condition and find it unsatisfied? — Each thread calls wait() again, releasing the lock. Eventually no thread holds the condition and all wait — if the notifying thread was the only one that would ever satisfy the condition, this is effectively a no-op cycle.

Related Questions

  • JVM vs JRE vs JDK
  • Java Platform Independence
  • How JVM Works
  • Main Features of Java
  • public static void main

Can You Explain This Cold?

Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.

Get Graded — Free Assessment
GrindQuestionsAITechnical interview assessment
TermsPrivacyAbout