I have finished reading Effective Java long time ago. It is such a great book. The more I passed through each page the more I realized how little I know about java programming. The distance between “coder” and “developer” is really far
I read most of the item listed in the book. One of the items I have skipped was Item 50: Never invoke wait outside a loop. The code below show the concept of this item
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
Looking at the name of the practice, I thought I knew all the reasons behind it so I just skipped it. Today I found an interesting post asking What is spurious wakeup (sadly the post is gone now). I read it and found that “threads can wake up on wait() for no reason at all”!!!!! There are quite many good references for this fact and one of them is, guess what, the item 50 of Effective Java. I would have known it for long time ago if I just read it. One of the reasons behind it stated in the item is that
The waiting thread could wake up in the absence of a notify. This is known as a spurious wakeup. Although The Java Language Specification [JLS] does not mention this possibility, many JVM implementations use threading facilities in which spurious wakeups are known to occur, albeit rarely [Posix, 11.4.3.6.1]
I thought sometimes it was OK to call wait() without condition-checking loop if the object to wait on represented just one condition, the object was shared only between waiting and notifying threads and the code’s execution order guaranteed that “wait leaks” would not occur. Now giving that JVM implementation can send spurious wakeup signal, the condition checking loop is A MUST
Apparently, the spurious wakeup is an issue (I doubt that it is a well known issue) that intermediate to expert developers know it can happen but it just has been clarified in JLS third edition which has been revised as part of JDK 5 development. The javadoc of wait method in JDK 5 has also been updated
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops
You may wonder (like me) why JLS designer decided to allow this kind of thing to happen. It’s not that I don’t want to use condition checking loop. The checking is the best practice that developers should always do no matter of them knowing anything about the spurious wakeup or not. But I just don’t see the benefit of allowing the wakeup for no reason. It turns out that this is something about performance as stated in Multithread Programming with Java
Due to some arcania in the hardware design of modern SMP machines, it proves to be highly convenient to define them like this. The hardware runs a little faster, and the programmer needs to reevaluate the condition anyway