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

🔔 notify() vs notifyAll() — Core Idea

notify()

  • Wakes up one random thread that’s waiting on the same object’s monitor (lock).
  • It’s not guaranteed which thread will be woken if multiple are waiting.
  • Only one continues; the others remain waiting.

notifyAll()

  • Wakes up all threads that are waiting on the object’s monitor.
  • But remember: only one of them can acquire the lock and proceed.
  • The rest go back to waiting until it’s their turn.

🔄 Example to Visualize It

Let’s say 3 threads are waiting on a lock:

synchronized (lock) {
    lock.wait();  // Thread A
}
synchronized (lock) {
    lock.wait();  // Thread B
}
synchronized (lock) {
    lock.wait();  // Thread C
}

Then:

🔔 If you call lock.notify();

  • Only one thread (say, Thread B) will wake up and try to acquire the lock.
  • A and C remain in waiting state.

🔔 If you call lock.notifyAll();

  • All threads (A, B, and C) are notified.
  • But only one can acquire the lock, others keep waiting until the lock is available.

📌 Summary Table

Featurenotify()notifyAll()
Wakes how many?🔸 One thread🔹 All waiting threads
Thread chosen?Random, not under your controlAll woken, one proceeds
PerformanceMore efficient (but risky)Slightly heavier (but safer)
RiskSome threads may starveAll get a chance eventually
UsageWhen only one needs to proceedWhen multiple threads may be eligible

✅ When to Use What?

Use notify():

  • When only one thread should proceed at a time, and it’s okay if others wait.
  • Example: one producer, one consumer.

Use notifyAll():

  • When multiple threads may be able to proceed, or you can’t predict which should.
  • Example: many threads waiting for a condition — safest to wake all.

🚨 Be Careful!

If you use notify() in a system with multiple consumers or producers, it may wake the wrong thread, leading to deadlocks or inefficiency.

That’s why notifyAll() is often the default safe choice in more complex systems.

🎯 The Risk: Waking a Thread That Can’t Proceed

When you use notify(), only one thread is woken — and you don’t control which one.

If that thread can’t do anything yet (its condition isn’t true), it will:

  1. Wake up,
  2. Re-check the condition (in the while loop),
  3. Go back to waiting.

Meanwhile, other threads that could have made progress remain stuck in waiting state 😬


🧪 Real Example: Multiple Consumers

Let’s say:

  • You have one producer
  • You have three consumers waiting for a task
  • But only one task is currently available: a task that only Consumer B can handle

Now:

  • Producer does:
synchronized (lock) {
    // adds task
    lock.notify();
}
  • If the JVM chooses Consumer A or C, and they can’t process that task, they’ll just go back to waiting

❗ Problem:

  • Nobody handles the task!
  • The thread that could do the job (Consumer B) is still waiting 😭

This can lead to:

  • Deadlocks
  • Starvation
  • Wasted CPU cycles

✅ How notifyAll() Solves This

If you write:

synchronized (lock) {
    // adds task
    lock.notifyAll();
}

Then:

  • A, B, and C are all woken up
  • They each check:
    • “Is this task for me?”
  • Only B proceeds, others go back to wait()

This guarantees that:

  • Whoever can proceed, will proceed
  • No one is accidentally left out

🎯 Summary: Why notify() is Risky

RiskDescription
Wrong thread wakes upWoken thread may not be able to proceed
Others stay sleepingThreads that could act remain blocked
Leads to inefficiencyCPU wasted, notifications lost, progress delayed
Can cause deadlocksIf no thread can proceed but all are waiting for someone to act

🔐 Rule of Thumb:

Use notifyAll() when multiple threads are waiting for different conditions.
Use notify() only when you’re 100% sure that any waiting thread can safely proceed.

This entry was posted in Без рубрики. Bookmark the permalink.