1

While I am reading java.util.concurrent.locks.Condition API documentation,

I see that:

When waiting upon a Condition, a "spurious wakeup" is permitted to occur, in general, as a concession to the underlying platform semantics. This has little practical impact on most application programs as a Condition should always be waited upon in a loop, testing the state predicate that is being waited for. An implementation is free to remove the possibility of spurious wakeups but it is recommended that applications programmers always assume that they can occur and so always wait in a loop

and the awaitUninterruptibly() says:

If the current thread's interrupted status is set when it enters this method, or it is interrupted while waiting, it will continue to wait until signalled. When it finally returns from this method its interrupted status will still be set

So, does it mean that we don't need to invoke awaitUninterruptibly() in loop ? Please clarify. Thanks in advance.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Ram Bavireddi
  • 1,139
  • 1
  • 19
  • 43
  • 1
    interrupts are not spurious wakeups, they still might happen. – Peter Lawrey Jan 14 '15 at 08:26
  • @PeterLawrey Will a thread invoking awaitUninterruptibly() continue to wait until signalled, without to be in a loop? – Ram Bavireddi Jan 14 '15 at 08:33
  • Only if it doesn't wake spuriously. – Peter Lawrey Jan 14 '15 at 08:35
  • 1
    @PeterLawrey Thanks for the demystification. Now understood that we are recommended to invoke any `wait()`s in a loop to deal with spurious wakeups. – Ram Bavireddi Jan 14 '15 at 08:58
  • It is possible you never see a spurious wake, but it is also likely you are in a processing loop already, waiting for something to happen. – Peter Lawrey Jan 14 '15 at 09:15
  • 1
    Always wait() in a loop. It's possible in some applications--likely even--that by the time a thread re-acquires the lock, and returns from a wait() call, the condition that it was waiting for has already become false again because of the activity of some other thread. Even if that can't happen in the application that you are writing today, The loop won't hurt the performance, and the habit of always using a loop may prevent you from making a mistake in your _next_ application. – Solomon Slow Jan 14 '15 at 19:40

2 Answers2

3

The specification is pretty clear:

void awaitUninterruptibly()

Causes the current thread to wait until it is signalled. The lock associated with this condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:

  • Some other thread invokes the signal() method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
  • Some other thread invokes the signalAll() method for this Condition; or
  • A "spurious wakeup" occurs.

So, interrupting is not on the list of possible wakeup conditions but spurious wakeup are. Don’t let you guide by looking into a particular piece of implementation code. The implementation your application finally runs on might be entirely different.

Further, Condition is an interface which might have different implementations even within one runtime environment. This answer doesn’t even specify which concrete class this code is from.

You have to perform the wait operation using the usual loop with awaitUninterruptibly().

Consider the following:

  • there is no 1:1 mapping between signal and wait,
    • hence you might miss one or more signals which occurred before your thread woke up
    • even worse, signals are not remembered and hence lost when they occurred before another thread started waiting
  • therefore you have to pre-check the desired conditional state before deciding to wait
  • this implies that a signal might wake up one thread but another one consumes the state due to a successful pre-check, hence the thread which woke up has to re-check the desired conditional state

Therefore, even without spurious wakeups a loop which pre-checks before waiting and re-checks after waking up is necessary.

Hearen
  • 7,420
  • 4
  • 53
  • 63
Holger
  • 285,553
  • 42
  • 434
  • 765
2

From the code:

public final void awaitUninterruptibly() {
  Node node = addConditionWaiter();
  int savedState = fullyRelease(node);
  boolean interrupted = false;
  while (!isOnSyncQueue(node)) {
    LockSupport.park(this);
    if (Thread.interrupted()) interrupted = true;
  }
  if (acquireQueued(node, savedState) || interrupted) selfInterrupt();
}

So the waiting is done in a loop, which would remove the need to loop that outside this function.

However keep in mind that this also means that Thread.interrupt() won't do anything, which might lead to certain lock-ups of your code, i.E. during shutdown.

TwoThe
  • 13,879
  • 6
  • 30
  • 54
  • The loop inside the method does a completely different thing than the loop that the application has to perform. The application’s loop has to check an application-specific condition that this method doesn’t even know. Besides that, you are mixing up a particular implementation code with a *contract*. – Holger Jan 16 '15 at 11:43