Re: notify / notifyAll misunderstanding

From: Chris Smith (cdsmith_at_twu.net)
Date: 07/13/04


Date: Tue, 13 Jul 2004 11:06:04 -0600

VisionSet wrote:
> As I understand it, notify wakes up a waiting thread that then attempts to
> gain lock the object it is waiting for. Where as notifyAll wakes up all
> waiting threads and ONLY ONE gains the lock, the others go back to waiting.

Not exactly. The code for the waiting looks something like this:

    synchronized (obj) // 1
    {
        ...

                        // 2
            obj.wait(); // 3
                        // 4

        ...
    } // 5

Note that I've left out the predicate NOT because it's unimportant, but
because it's irrelevant to the point I'm making.

Now, when a thread begins this code it first grabs the monitor for obj,
meaning it can be the only thread running that has that monitor. Just
before it enters a wait state, and checkpoint 2, it atomically releases
that monitor and then enters the wait state. When it is woken, it
regains the monitor. (Actually, steps 2, 3, and 4 all take place inside
the wait call, but this is the easiest way to represent this in text.)
Finally, when it's done, it releases that monitor again.

Let's draw distinction between waiting and blocked. A thread that's
waiting is at checkpoint 3 in the code above. It is waiting for a
notify to happen, NOT for a monitor to be released. A thread that's
blocked is at checkpoint 1 or 4 above. It is blocked on a monitor, NOT
waiting for notify, so a call to notify won't affect it. In the case of
notifyAll() above, every single one of the threads that's waiting at #3
will move to #4, and THEN try to gain the monitor. At that point, none
of these threads are waiting; they are all blocked instead.

So here's the difference. In the notify() case, only one thread leaves
the waiting state, and it gains the monitor at #4 and then possibly
discovers that its predicate has not been fulfilled, so it goes back to
sleep. Then you're stuck. (It's not guaranteed to be that way; the
order in which threads are returned from a wait() state is not
specified, so it's actually possible that the one thread waiting on 5
will be the one that is woken up, and you will see something different.)

In the notifyAll() case, every single waiting thread is woken, and they
all line up at #4, and then (because of the monitor), they take turns
checking their predicates. The one that's looking for 5 WILL eventually
make it through, and it will continue on its merry way.

You've given an example here of a case where it's not safe to use plain
notify() on a monitor. Specifically, since different threads have
different predicates, you have no way of knowing whether the thread you
happen to wake up will be the one that cares about the notification, so
you have to use notifyAll. If all your threads were symmetrical, so
that they were all waiting for the same thing and only one would be able
to respond, then notify() would be valid.

The rule is this: use notifyAll(), and then replace it with notify()
only when the waiting threads are interchangeable.

-- 
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation


Relevant Pages

  • Re: The condition variable test
    ... In many cases, there may be more than one reason for waiting, and these ... As the simplest example of a monitor, ... details associated with condition variables. ... constraints at all on when the waiting process must run after a NOTIFY. ...
    (comp.programming.threads)
  • Re: notfiy() and wait()
    ... is the current state of the intersection: ... Simple: The "BEEP" signals ... should not be) waiting for a signal, ... makes the change it calls notify() *not* to tell you that you can ...
    (comp.lang.java.programmer)
  • Re: How to notify specific thread??
    ... > while loop is false the wait is invoked on the thread. ... > But I would like to be able to notify only the correct thread. ... It is impossible to notify a specific thread that's waiting on a ... then you can split the monitor into several monitors. ...
    (comp.lang.java.help)
  • Re: Producer - Consumer Threads why use "while" loop instead of "if"?
    ... It's just always written in the books that that is ... The other reason is that using notify() rather than notifyAllis fragile. ... actually waiting on the object in question. ... > check out any standard Java book that teaches threads). ...
    (comp.lang.java.programmer)
  • Re: illegalMonitorStateException
    ... you are waiting for *something* to ... because the notify() that it was waiting for has ... checking the predicate and wait ... That's true for two distinct reasons: ...
    (comp.lang.java.programmer)