[concurrency-interest] spurious wakeups semantics
dholmes at dltech.com.au
Thu Nov 3 19:38:08 EST 2005
I know I should just sit back and keep quiet but ... :)
Peter is right (as another Peter (Buhr uC++) not on this list would
strenuously agree) in the absence of spurious wakeups it is possible to
write code that need not wait() in a loop, and in some cases (much fewer)
not even check a condition before waiting.
However it is far more common for people to write code that will be
incorrect in the absence of the loop (even people that should know better).
So the mantra has always been "always test your condition in a loop" - with
a footnote: unless you can prove it is safe to do otherwise. Spurious
wakeups reinforce this and help to avoid errors that would otherwise occur.
(This is a similar argument Dave Butenhof makes for the POSIX pthreads
semantics for condition variables - which Java essentially borrowed from).
Spurious wakeups have a history steeped in myth and mystery. No one is
really sure where they came from. The POSIX rationale shows a piece of
broken code and uses that to justify the possibility of spurious wakeups.
Legend has it that some early multi-processor (Firefly is often named but
I've never seen any supporting documentation) might mistakenly wakeup more
than one thread that was waiting - hence they were woken spuriously (this is
somewhat supported by POSIX's pthread_cond_signal semantics that state that
"unblocks at least one thread" - at least Java didn't copy to that
Peter is also right that the VM could shield the runtime and the application
from these obscure possibilities. But as Tim pointed out the cost-to-benefit
ration just doesn't justify it. Language purists will no doubt disagree, but
offending one's aesthetic and engineering sensibilities by needing to use a
while loop, is hardly a significant matter***. Java isn't going to change so
just grin-and-bear it.
** By the way. Another aspect of this is whether, considering POSIX, a
spurious wakeup was only meant to account for a signal waking more than one
thread, or whether it could occur even in the absence of any signals.
(Unless you use waiting as a sleep mechanism, I don't think there is any
practical difference between the two.)
*** I do understand however that it makes formal modelling more difficult
due to the need to establish that the loop terminates. As long as such
models don't assume that spurious wakeups can occur infinitely often, their
only affect is a time delay. You still need to establish that any waiting
thread will eventually have its reason for waiting satisfied.
Probably best to stop there. :-)
More information about the Concurrency-interest