Card 06/ 09

GotchaDifficulty: Advanced1 min

Why Your Loop Never Noticed the Flag Another Thread Set

The shutdown request is logged, the flag is set, and the worker keeps running. Attaching a debugger makes it stop, which is the most annoying possible symptom.

java
boolean stopped = false;

while (!stopped) { doWork(); }

Nothing in the loop writes stopped, so the virtual machine is entitled to read it once and keep the value in a register. As far as a single thread's own view is concerned, that is identical behaviour — and it is why the loop never sees the change.

java
volatile boolean stopped = false;

volatile says that every read of this field must go and look, and every write must be published where other threads will see it. The loop now notices the change on its next pass.

volatile fixes visibility and nothing else. A volatile int still loses increments, because count++ is still three steps — it is now three steps everybody can see.