Having three threads waiting on a 4th one, and the latter issuing a notify, all of the waiting threads are awakened.
Here is the source code:
class Reader extends Thread {
Calculator calc;
public Reader(Calculator calc) {
this.calc = calc;
}
public void run() {
synchronized(calc) {
try {
System.out.println(Thread.currentThread().getName() + " waiting for calc");
calc.wait();
} catch (InterruptedException e) { e.printStackTrace(); }
System.out.println(Thread.currentThread().getName() + " Total is: " + calc.total);
}
}
}
class Calculator extends Thread {
public int total = 0;
public void run() {
synchronized(this) {
for (int i = 0; i < 50; i++) {
total += i;
}
notify();
System.out.println("I notified a thread");
}
}
}
public class Notify {
public static void main(String[] args) {
Calculator calc = new Calculator();
Reader r1 = new Reader(calc);
Reader r2 = new Reader(calc);
Reader r3 = new Reader(calc);
r1.start();
r2.start();
r3.start();
calc.start();
}
}
Here is the output I get:
Thread-2 waiting for calc
Thread-4 waiting for calc
Thread-3 waiting for calc
I notified a thread
Thread-2 Total is: 1225
Thread-3 Total is: 1225
Thread-4 Total is: 1225
Shouldn't only one waiting thread be awakened and execute the System.out.println(Thread.currentThread().getName() + " Total is: " + calc.total); instruction ?
You can't use wait/notify this way. You have to use wait to wait for something, something your code can, and must, test. You should only call notify after changing something that another thread is actually waiting for such that its test will tell it to no longer wait for it.
"A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied."
In other words, your wait logic must look like this:
wait and go to step 1.And your notify logic must look like this:
notify.These functions are not a generic suspend/resume mechanism. They are specifically a way to synchronize on a predicate managed by code protected by the synchronized block. You can build a suspend/resume mechanism out of them if you want by using your own suspect/resume flag or count if you want to.
Update: Måns Rolandi Danielsson figured out what's going on in your specific case. Your threads are waiting for an object that hasn't launched/terminated already. So when it signals itself that it is ready/finished, the other threads see that signal.
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