Usenet Poster!!! wrote:
> I've been going over some code with a colleague on thread
> synchronization
> and he used an 'if' instead of a 'while' loop to wait().
> [... stack-pop implementation snipped ...]
> The notify() statement will only notify 1 thread, so how could another
> thread consume (pop) if i was the only thread notified and woken up
> (since the rest are still waiting)?
Others have mentioned that wait() might awaken for
unanticipated reasons, and have talked about notify()
vs. notifyAll(). Here's another scenario:
Thread A finds the stack empty and puts itself
to sleep with wait().
Thread B pushes something on the stack and
calls notify() to awaken A.
"Awakening" is not instantaneous. Not only
that, but A needs to re-aquire the lock. And
while all this is going on ...
... Thread C, which has been happily running
all this time, chooses this moment to pop the
stack. It finds the stack non-empty, removes
the object B put there, and goes about its
business without ever wait()ing at all.
Finally, Thread A finishes rubbing the sleepy
sand from its eyes and finds itself awake and
running, just after the wait().
Now: Is it safe for A to pop an object off the top of
the stack? No -- the stack is empty because C has already
popped it. Thread A must re-test the "stack empty"
condition and go back to sleep again.
Another way to look at the situation is to realize
that the state of a shared object can change at any time
while you're not holding its lock. Some period of time
elapses between the notify() or notifyAll() and the moment
when the awakened thread re-acquires the lock, and the
state of the object can change during that time.
--