Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does 'notify' wake up all waiting threads although only one thread should be affected?

In the following code two consumer threads start and become waiting. The producer thread starts (very likely) after that and calls 'notify'. All threads use the producer as monitor.

Thread producer = new Thread() { 
    @Override
    public void run() {
        synchronized (this) {
            System.out.printf("notify at %d %n", getId());
            notify();
        }
    }
};

Runnable consumer = () -> {
    try {
        synchronized (producer) {
            long id = Thread.currentThread().getId();
            System.out.printf("wait at %d %n", id);
            producer.wait();
            System.out.printf("awakened: %d %n", id);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
};

Stream.generate( () -> consumer )
        .limit(2)
        .map(Thread::new)
        .forEach(Thread::start);

Thread.sleep(3000); // consumer threads are (likely) waiting

producer.start();

From javadoc for Object.notify:

Wakes up a single thread that is waiting on this object's monitor.

The code produces this (or similar) output:

  wait at 13 
  wait at 14 
  notify at 12 
  awakened: 13 
  awakened: 14 

The point is that both consumer threads are awakened, not just one of them. Why?

Compiled and tested with OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.5+10) under Windows 10, 64-bit.

Thanks in advance!

like image 211
L. Hummel Avatar asked Jan 01 '23 06:01

L. Hummel


1 Answers

The issue is that instead of an arbitrary Object you use a Thread as the monitor.

Thread uses signals internally as documented in Thread.join:

As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

The general suggestion is to always use dedicated objects to wait/notify on that no other code can get access to to avoid "spurious" notifies or waits like this.

like image 95
Joachim Sauer Avatar answered Jan 14 '23 15:01

Joachim Sauer