Do Spurious Wakeups in Java Actually Happen

Do spurious wakeups in Java actually happen?

The Wikipedia article on spurious wakeups has this tidbit:

The pthread_cond_wait() function in Linux is implemented using the futex system call. Each blocking system call on Linux returns abruptly with EINTR 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 the futex 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.

Are spurios wakeups accompanied by an InterruptedException?

Usually obj.wait(...) should wait until someone calls obj.notify() (or until the timeout is reached), but as the documentation states:

A thread can 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. See the example
below

Due to spurious wakeup the thread might wakeup without being notified. That is why it is essential to check the guard condition of the monitor in a loop (example taken from the javadoc as well):

synchronized (obj) {
while (<condition does not hold> and <timeout not exceeded>) {
long timeoutMillis = ... ; // recompute timeout values
int nanos = ... ;
obj.wait(timeoutMillis, nanos);
}
... // Perform action appropriate to condition or timeout
}

If you're using a timeout, you should check, if the timeout is exceeded as well.

This has nothing to do with handling interrupted exceptions. Those won't be thrown spuriously, but only if the current thread is really interrupted. That is in your spurious-loop you don't need to add handling for InterruptedException

Do spurious wakeups affect Thread.sleep?

You're asking whether Thread.sleep() is affected by the same spurious wakeup issue that is documented to affect Object.wait(long), right? The answer is that there is no documented spurious wakeup associated with Thread.sleep(). You're right that no hard guarantees are made about exactly how long you'll sleep when you request N milliseconds. Also, of course, Thread.sleep() terminates on thread interrupt.

Forcing a spurious-wake up in Java

You can't force a spurious wakeup, but to the running thread, a spurious wakeup is indistinguishable from a regular wakeup (the source of the event is different, but the event itself is the same)

To simulate a spurious wakeup, simply call notify();

Calling interrupt() isn't suitable, because doing so sets the interrupt flag, and after a spurious wakeup, the interrupt flag is not set

Is CountDownLatch affected by spurious wakeups?

The javadoc of CountDownLatch#await() states

If the current count is greater than zero then the current thread
becomes disabled for thread scheduling purposes and lies dormant until
one of two things happen:

  • The count reaches zero due to invocations of the countDown() method; or
  • Some other thread interrupts the current thread.

dormant meaning the method won't return. In other words, though a spurious wakeup can occur, it won't cause the await method to return.

You can look at the implementation to see how this is done exactly, but, in brief, it's the typical trick of looping and "waiting" (through LockSuport#park or Object#wait which are affected by spurious wakeups) until a condition is met.

When it comes to CountDownLatch, are spurious wakeups an issue?

No.

Meaning and hazard of spurious wakeups in Java?

The JVM is allowed to wake a waiting thread without another thread calling its notify() method - a so called "spurious wakeup".

If you don't consider this possibility, you may proceed with processing when the wait state has not been achieved, leading to incorrect behaviour.

The correct approach when woken up is to first check that the state your thread is waiting on has actually been achieved, otherwise return to waiting by immediately calling wait()

When should I worry about spurious wakeups when using java.util.concurrent classes

Going off of this question: Can Semaphore.acquire() throw InterruptedException due to a spurious wakeup?

It appears that a spurious wakeup does not actually interrupt the thread, so it seems that you don't need to have the try/catch there (edit: for a spurious wakeup, that is. You still need to have it in case the waiting thread is actually interrupted).

According to the first answer there:

"It is "spurious wakeup" not "spurious interrupt": "A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup." There is no InterruptedException thrown during a spurious wakeup. As you say in the comments: The thread wakes up but the interrupted flag is not set"

Java concurrent - spurious wakeups and wait(timeout)

here's how i typically handle this:

long timeout = ....;
synchronized(obj) {
long start = System.currentTimeMillis();
while(!condition && (timeout > 0)) {
obj.wait(timeout);
long now = System.currentTimeMillis();
timeout -= (now - start);
start = now;
}
}

Can we have spurious interrupts?

Yes, you should be introduce a volatile boolean to control the loop. Not just because of the possibility of a spurious interrupt, but because it makes the code more readable.

You're not achieving a clever optimization by "saving" a boolean and using the interrupt status of the thread to control the loop, you're making it less obvious as to what the working mechanism of the class is.

Edit: I wasn't really answering the core question (mixed it up with wakeups). As we know, spurious wakeups can and do happen, which is why we use guard clauses/loops to check that a condition has really been satisfied.

Spurious interrupts aren't a thing, meaning there's always one thread interrupting another inside the Java ecosystem (unlike with wakeups, where the reason is external). Interrupting random threads is not something that the Java platform does by itself, but you could write a thread that just randomly selects other threads and tries to interrupt them. However that wouldn't be a spurious interrupt, that would be a malicious interrupt.



Related Topics



Leave a reply



Submit