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!
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 usewait
,notify
, ornotifyAll
onThread
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With