Answering the OP's question
What can I do to wake this await up spuriously without waiting forever
for a random event?
, no any spurious wakeup could wake up this awaiting thread!
Regardless of whether spurious wakeups can or cannot happen on a particular platform, in a case of the OP's snippet it is positively impossible for Condition.await()
to return and to see the line "Spurious wakeup!"
in the output stream.
Unless you are using very exotic Java Class Library
This is because standard, OpenJDK's ReentrantLock
's method newCondition()
returns the AbstractQueuedSynchronizer
's implementation of Condition
interface, nested ConditionObject
(by the way, it is the only implementation of Condition
interface in this class library),
and the ConditionObject
's method await()
itself checks whether the condition does not holds and no any spurious wakeup could force this method to mistakenly return.
By the the way, you could check it yourself as it is pretty easy to emulate spurious wakeup once the AbstractQueuedSynchronizer
-based implementation is involved.
AbstractQueuedSynchronizer
uses low-level LockSupport
's park
and unpark
methods, and if you invoke LockSupport.unpark
on a thread awaiting on Condition
, this action cannot be distinguished from a spurious wakeup.
Slightly refactoring the OP's snippet,
public class Spurious {
private static class AwaitingThread extends Thread {
@Override
public void run() {
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();
}
}
}
private static final int AMOUNT_OF_SPURIOUS_WAKEUPS = 10;
public static void main(String[] args) throws InterruptedException {
Thread awaitingThread = new AwaitingThread();
awaitingThread.start();
Thread.sleep(10000);
for(int i =0 ; i < AMOUNT_OF_SPURIOUS_WAKEUPS; i++)
LockSupport.unpark(awaitingThread);
Thread.sleep(10000);
if (awaitingThread.isAlive())
System.out.println("Even after " + AMOUNT_OF_SPURIOUS_WAKEUPS + " \"spurious wakeups\" the Condition is stil awaiting");
else
System.out.println("You are using very unusual implementation of java.util.concurrent.locks.Condition");
}
}
, and no matter how hard the unparking(main) thread would try to awake the awaiting thread, the Condition.await()
method will never return in this case.
The spurious wakeups on Condition
's awaiting methods are discussed in the javadoc of Condition
interface .
Although it does say that,
when waiting upon a Condition, a spurious wakeup is permitted to occur
and that
it is recommended that applications programmers always assume that they can occur and so always wait in a loop.
but it later adds that
An implementation is free to remove the possibility of spurious wakeups
and AbstractQueuedSynchronizer
's implementation of Condition
interface does exactly that - removes any possibility of spurious wakeups.
This surely holds true for other ConditionObject
's awaiting methods.
So, the conclusion is :
we should always call Condition.await
in the loop and check if the condition does not hold, but with standard, OpenJDK, Java Class Library is can never happen.
Unless, again, you use very unusual Java Class Library (which must be very very unusual, because another well-known non-OpenJDK Java Class Libraries, currently almost extinct GNU Classpath and Apache Harmony, seems to have identical to standard implementation of Condition
interface)
pthread_cond_wait()
the real question is "Why does pthread_cond_wait have spurious wakeups?". – Hillery