volatile : Java Glossary
©1996-2017 2010-02-12 Roedy Green of Canadian Mind Products
The volatile keyword is used on variables that may be
modified simultaneously by other threads. This warns the compiler to fetch them fresh
each time, rather than caching them in registers. This also inhibits certain
optimisations that assume no other thread will change the values unexpectedly. Since
other threads cannot see local variables, there is never any need to mark local
variables volatile. You need synchronized to coordinate changes to variables from different
threads, but often volatile will do just to look at
Just What Does volatile Guarantee?
What volatile does is subtle, tying into the rest
of the memory model, so there isn’t a simple way to isolate it in this short
explanation — but the memory model section in the JLS (Java Language Specification)
explains it well. Now that you have read this overview to give you the general idea
of what volatile does, you need to read the
to understand the fine points.
- The main thing volatile does is suppress the
compiler/Hotspot from caching the value of the variable in registers. Every time
its value changes, the generated code immediately flushes the value to
RAM (Random Access Memory) where other threads can see it.
- For references and all primitives (except sometimes long), two threads will always see a complete value, never one
half-way modified by another thread. The official term for such an intact atomic
value is a consistent value.
- Prior to Java version 1.5, volatile did not guarantee the atomicity of a 64-bit long load or store. A second
thread could view the value when only 32 bits of the
new value had been stored, getting half the old value and half the new. The
hardware of the day could not efficiently implement 64-bit atomicity. Starting with Java version 1.5,
atomicity of volatile longs is guaranteed, on
64-bit hardware, 32-bit
hardware and even hardware that requires software dodges to ensure atomicity. If
the CPU (Central Processing Unit) has no hardware support for 64-bit atomicity, the JVM (Java Virtual Machine)
can pull it off by redirecting an atomic 32-bit pointer
to a freshly stored 64-bit value. The problem is
32-bit hardware has to store a long in two 32-bit pieces and you can
thus access a half-stored non-volatile long.
For example, the semantics of volatile are not
strong enough to make the increment operation (x++) atomic, unless you can
guarantee that the variable is written only from a single thread.Atomicity of ++ on volatile variables (or non-volatile
for that matter) is not guaranteed. volatile x ++ is treated as load x, add 1, store x. A second thread doing
x ++ could interleave,
causing x to be incremented only once.
Java Concurrency in Practice
- The visibility effects of volatile variables
extend beyond the value of the volatile variable
itself. When thread A writes to a volatile variable
and subsequently thread B reads that same variable, the values of
all variables that were visible to A prior to writing to the
volatile variable become visible to B after reading
the volatile variable.