← Back to Home

Inter-Thread Communication

Inter-thread communication in Java allows multiple threads to coordinate and cooperate when working on shared data. It is primarily achieved using the wait(), notify(), and notifyAll() methods of the Object class, in conjunction with synchronization. This is a very high-frequency interview topic, especially with producer–consumer scenarios.

Why Inter-Thread Communication Is Needed

Without coordination, threads may:

  • Run in the wrong order
  • Waste CPU cycles (busy waiting)
  • Read inconsistent data
  • Cause race conditions

Goal: Enable threads to pause, resume, and signal each other safely.

Core Methods for Inter-Thread Communication

All belong to java.lang.Object:

Method Purpose
wait() Releases lock and waits
notify() Wakes up one waiting thread
notifyAll() Wakes up all waiting threads

Important Rule (Interview Favorite)

wait(), notify(), and notifyAll() must be called inside a synchronized context.

Otherwise: IllegalMonitorStateException

How wait() Works

  • Causes the current thread to release the monitor lock
  • Thread enters WAITING or TIMED_WAITING state
  • Thread resumes only after:
  • notify() / notifyAll()
  • Re-acquiring the lock
synchronized (lock) {
    lock.wait();
}
          

How notify() Works

  • Wakes one arbitrary waiting thread
  • Does not release the lock immediately
  • Lock is released only after synchronized block exits
synchronized (lock) {
    lock.notify();
}
          

How notifyAll() Works

  • Wakes all waiting threads
  • Threads compete to re-acquire the lock
  • Safer when multiple conditions exist
synchronized (lock) {
    lock.notifyAll();
}
          

Thread State Transitions

Method State Change
wait() RUNNABLE → WAITING
notify() WAITING → BLOCKED
Lock acquired BLOCKED → RUNNABLE

Classic Example: Producer–Consumer Problem

Shared Resource

class SharedBuffer {
    private int data;
    private boolean available = false;

    synchronized void produce(int value) throws InterruptedException {
        while (available) {
            wait();
        }
        data = value;
        available = true;
        System.out.println("Produced: " + value);
        notify();
    }

    synchronized int consume() throws InterruptedException {
        while (!available) {
            wait();
        }
        available = false;
        System.out.println("Consumed: " + data);
        notify();
        return data;
    }
}
          

✔ Uses while, not if

✔ Avoids spurious wakeups

Why while Is Used Instead of if (Very Important)

  • Threads may wake up without condition being true
  • Multiple threads may be notified
  • while rechecks condition
while (!condition) {
    wait();
}
          

wait() vs sleep() (Common Interview Trap)

Aspect wait() sleep()
Releases lock ✔ Yes ❌ No
Called on Object Thread
Used for Coordination Pause
Requires synchronized ✔ Yes ❌ No

notify() vs notifyAll()

Aspect notify() notifyAll()
Threads awakened One All
Performance Better Slower
Safety Risky Safer
Use case Single-condition Multiple conditions

Common Mistakes

  • Calling wait() outside synchronized block
  • Using if instead of while
  • Using notify() when multiple threads wait
  • Synchronizing on wrong object
  • Forgetting condition flags

Best Practices (Production-Grade)

  • Always use wait() in a while loop
  • Prefer notifyAll() for correctness
  • Keep synchronized blocks small
  • Clearly define condition variables
  • Consider java.util.concurrent alternatives

Modern Alternatives (Preview)

Instead of low-level wait/notify:

  • BlockingQueue
  • CountDownLatch
  • CyclicBarrier
  • Semaphore

✔ Safer

✔ Easier to maintain

✔ Preferred in enterprise code

Interview-Ready Answers

Short Answer

Inter-thread communication allows threads to coordinate using wait, notify, and notifyAll.

Detailed Answer

In Java, inter-thread communication is achieved using wait(), notify(), and notifyAll() methods of the Object class. These methods allow threads to release locks, wait for conditions, and signal other threads, enabling safe coordination and avoiding busy waiting in multithreaded programs.

Key Takeaway

wait() releases the lock.

notify() signals waiting threads.

notifyAll() ensures correctness.

Inter-thread communication is powerful but error-prone—use it carefully or prefer high-level concurrency utilities.