Do spurious wakeups in Java actually happen?
Seeing various locking related question and (almost) always finding the 'loop because of spurious wakeups' terms1 I wonder, has anyone experienced such kind of a wakeup (assuming a decent hardware/software environment for example)?
I know the term 'spurious' means no apparent reason but what can be the reasons for such kind of an event?
(1 Note: I'm not questioning the looping practice.)
Edit: A helper question (for those who like code samples):
If I have the following program, and I run it:
public class Spurious {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
lock.lock();
try {
try {
cond.await();
System.out.println("Spurious wakeup!");
} catch (InterruptedException ex) {
System.out.println("Just a regular interrupt.");
}
} finally {
lock.unlock();
}
}
}
What can I do to wake this await
up spuriously without waiting forever for a random event?
Solution 1:
The Wikipedia article on spurious wakeups has this tidbit:
The
pthread_cond_wait()
function in Linux is implemented using thefutex
system call. Each blocking system call on Linux returns abruptly withEINTR
when the process receives a signal. ...pthread_cond_wait()
can't restart the waiting because it may miss a real wakeup in the little time it was outside thefutex
system call. This race condition can only be avoided by the caller checking for an invariant. A POSIX signal will therefore generate a spurious wakeup.
Summary: If a Linux process is signaled its waiting threads will each enjoy a nice, hot spurious wakeup.
I buy it. That's an easier pill to swallow than the typically vague "it's for performance" reason often given.
Solution 2:
I have a production system that exhibits this behaviour. A thread waits on a signal that there is a message in the queue. In busy periods, up to 20% of the wakeups are spurious (ie when it wakes there is nothing in the queue). This thread is the only consumer of the messages. It runs on a Linux SLES-10 8-processor box and is built with GCC 4.1.2. The messages come from an external source and are processed asynchronously because there are problems if my system does not read them fast enough.