Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - notifyAll() and notify() failed? Is it possible?

Tags:

java

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

  1. A prints out string from C
  2. A sends request to B and wait(10)
  3. B notify() A ......

  4. 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?

like image 517
zx_wing Avatar asked Nov 04 '22 05:11

zx_wing


1 Answers

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();
}
like image 194
Peter Lawrey Avatar answered Nov 07 '22 20:11

Peter Lawrey