This is really weird to me, but looks like notifyAll()/notify() failed in my program. The code is rather complicated, basically I have three threads A, B, C
A sends request to B and wait() on the request with a 10 secs timeout, when B finishes, it calls notify() to wake up A.
C in a deadloop feeds a lot of strings to A through a queue, A picks up them and prints out. Each time A print out a string it sends a request to B and wait.
So the workflow comes to be:
C keeps feeding a in deadloop
B notify() A ......
A prints out string from C .... again and again ....
This works in first a few seconds. however, after a while I see when B prints out that it has notify() A, A is still waiting because the queue which C uses to feed A is getting increased quickly, and no string gets printed by A. Finally, after 10 secs, A complains the request timeout.
This looks like the notify() failed because B printed out message after it called notify(). Given wait/notify is radical feature of java, I can not believe it will fail. Is it possible?
notify() will only work if there is a thread wait()ing for it at that time.
The idiom you should use is to change a state in the same synchronized block as notify()/notifyAll(). In the waiting block, you repeatedly check for the state change. That way if the notify was triggered too early there is a state change to record it. Also if wait wakes spuriously it will wait again if the state hasn't changed.
public synchronized void notifyReady() {
ready = true;
notifyAll();
}
public synchronized void waitForReady() throws InterruptedException {
while(!ready)
wait();
}
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