Re: notify / notifyAll misunderstanding
From: Chris Smith (cdsmith_at_twu.net)
Date: 07/13/04
- Next message: John C. Bollinger: "Re: notify / notifyAll misunderstanding"
- Previous message: VisionSet: "Re: notify / notifyAll misunderstanding"
- In reply to: VisionSet: "notify / notifyAll misunderstanding"
- Next in thread: VisionSet: "Re: notify / notifyAll misunderstanding"
- Reply: VisionSet: "Re: notify / notifyAll misunderstanding"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
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
- Next message: John C. Bollinger: "Re: notify / notifyAll misunderstanding"
- Previous message: VisionSet: "Re: notify / notifyAll misunderstanding"
- In reply to: VisionSet: "notify / notifyAll misunderstanding"
- Next in thread: VisionSet: "Re: notify / notifyAll misunderstanding"
- Reply: VisionSet: "Re: notify / notifyAll misunderstanding"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|
|