Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: edita

The Object.wait() method is used to temporarily cede possession of a lock so that another requesting thread can proceed. It must always be used inside a synchronized block or method. To let the waiting thread resume, the requesting thread must notify it. Furthermore, the wait() method should be invoked in a loop that checks if a condition predicate holds. The correct way to invoke wait() is shown below.

Code Block

synchronized (object) {
  while (<condition does not hold>) {
    object.wait(); 
  }

  // Proceed when condition holds
}

The invocation of notify() or notifyAll() in another thread cannot precisely determine which waiting thread must be resumed. A condition predicate statement is used so that the correct thread resumes when it receives a notification. A condition predicate also helps when a thread is required to block until a condition becomes true, for instance, when it cannot should not proceed without obtaining reading some data from an input stream.

...

...


synchronized (object) {
  while (<condition does not hold>) {
    object.wait(); 
  }

  // Proceed when condition holds
}

Two properties come into the picture:

...

Wiki Markup
To guarantee _safety_, the {{while}} loop condition must be tested even after theinvoking call to {{wait()}}. While {{wait()}} is meant to block indefinitely until a notification is received, this practice is recommended because: \[[Bloch 01|AA. Java References#Bloch 01]\] 

  • Thread in the middle: A third thread can acquire the lock on the shared object during the interval between a notification being sent and the receiving thread actually resuming execution. This thread can change the state of the object leaving it inconsistent. This is a time of check, time of use (TOCTOU) condition.
  • Malicious notifications: There is no guarantee that a random notification will not be received when the condition does not holdpredicate evaluates to false. This means that the invocation of wait() is may be nullified by the notification.
  • Mis-delivered notification: Sometimes on receipt of a notifyAll() signal, an unrelated thread can start executing and it is possible for its condition predicate to be true. Consequently, it may resume execution whilst it was required to remain blockeddormant.
  • Wiki Markup
    Spurious wakeups: Certain JVM implementations are vulnerable to _spurious wakeups_ that result in waiting threads waking up even without a notification \[[API 06|AA. Java References#API 06]\].

Because of these reasons, it is indispensable to check the condition using a loop, after after wait() is invoked. A while loop is the best choice to check the condition before and after invoking wait() is called.

Wiki Markup
Similarly, the {{await()}} method of interface {{Condition}} must also be invoked inside a loop. According to the Java API \[[API 06|AA. Java References#API 06]\], Interface {{Condition}}:

...

Newer code should use the java.util.concurrent concurrency utilities as opposed to the wait/notify mechanism, however, legacy code may require use of these methods.

Noncompliant Code Example

...

Code Block
bgColor#FFcccc
synchronized(object) {
  if(<condition does not hold>)
    object.wait();
  //proceed Proceed when condition holds
}

Compliant Solution

This compliant solution encloses the wait() method in a while loop and as a result checks the condition during both pre and post wait() invocation times.

Code Block
bgColor#ccccff
// The condition predicate guards a lock on the shared object/variable
synchronized (object) {
  while (<condition does not hold>) {
    object.wait(); 
  }

  // Proceed when condition holds
}

LikewiseSimilarly, if the await() method of the java.util.concurrent.locks.Condition interface is implemented, it should be enclosed in a loop.

...