Why does java.util.concurrent.ArrayBlockingQueue use ‘while’ loops instead of ‘if’ around calls to await()?

To protect against spurious wake ups. There is no guarantee made to you by the JVM that the only possible reason the thread will ever start running again is because you called signal in the way you intended. Sometimes it will just get started accidentally and go (Spurious wake up). So you have to keep waiting again if the condition you want to run on isn’t actually true.

This is explained in the javadoc for the wait method:
http://java.sun.com/javase/6/docs/api/java/lang/Object.html#wait%28long%29

And mentioned in the docs for await:
http://java.sun.com/javase/6/docs/api/java/util/concurrent/locks/Condition.html#await%28%29

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 four 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

  • Some other thread interrupts the current thread, and interruption of
    thread suspension is supported; or

* A “spurious wakeup” occurs.

Some implementations of the Condition interface may suppress spurious wakeups, but relying on that would hence be relying on an implementation detail and makes your code unportable.

Leave a Comment