Ram Bavireddi
Ram Bavireddi

Reputation: 1187

java.util.concurrent.locks.Condition awaitUninterruptibly()

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.

Upvotes: 1

Views: 1578

Answers (2)

Holger
Holger

Reputation: 298429

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.

Upvotes: 3

TwoThe
TwoThe

Reputation: 14289

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.

Upvotes: 2

Related Questions