Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: reordered text

...

However, the compiler is free to read the field this.done once and to reuse the cached value in each execution of the loop. Consequently, the while loop might never terminate, even when another thread calls the shutdown() method to change the value of this.done [JLS 2011]. This error could have resulted from the programmer incorrectly assuming that the call to Thread.sleep() would cause causes cached values to be reloaded.

...

A better solution for methods that call sleep() is to use thread interruption, which causes the sleeping thread to wake immediately and handle the interruption. Note that the interrupting thread must know which thread to interrupt; logic for tracking this relationship has been elided.

Code Block
bgColor#ccccff
final class ControlledStop implements Runnable {

  @Override public void run() {
    // Record current thread, so others can interrupt it
    myThread = currentThread();
    while (!Thread.interrupted()) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      }
    }
  }

  public void shutdown(Thread th) {
    th.interrupt();
  }
}

Note that the interrupting thread must know which thread to interrupt; logic for tracking this relationship has been elided.

Noncompliant Code Example (getState())

...

This compliant solution removes the check for determining whether the thread is in the WAITING state. This check is unnecessary because invoking notifyAll() affects only threads that are blocked on a wait() invocation. 

Code Block
bgColor#ccccff
public class Waiter {
  // ...
  private Thread thread;
  private volatile boolean flag;
  private final Object lock = new Object();

  public boolean stop() {
    if (thread != null) {
      synchronized (lock) {
        flag = true;
        lock.notifyAll();
      }
      return true;
    }
    return false;
  }
}

That check is unnecessary because invoking notifyAll() affects only threads that are blocked on a wait() invocation.

Applicability

Relying on the Thread class's sleep(), yield(), and getState() methods for synchronization control can cause unexpected behavior.

...