Card 06/ 09
volatile: Why a Loop Never Sees the Flag Another Thread Set
The worker keeps running after shutdown, and attaching a debugger makes it stop.
volatile on a field makes every write to it visible to every thread, and every read fetch the current value. A loop that checks a stop flag without it may never see the flag change, and that is the most common visibility bug in Java: a write one thread makes that another thread never sees.
The shutdown request is logged, the flag is set, and the worker keeps running. Attaching a debugger makes it stop, which is the most confusing symptom possible:
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, a slot inside the processor that is never refreshed from memory. From the single thread's own point of view that behaves identically, and it is why the loop never sees the change.
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; they are now three steps every thread can see.
← → move through sections and cards