> When simultaneously accessing a field from two or more
> threads, the access must be synchronized.
This is overstated. When simultaneously MODIFYING a variable from two
or more threads, the access almost always must be synchronized. You
can safely read an ordinary primitive (except long or double) from any
thread, although you might get an old value instead of the current
value. You can safely read a volatile primitive (including long and
double) from any thread and be assured that you are getting the
> The volatile
> declaration simply means that any particular individual
> access (fetch or store) will process all bits in parallel
> for that single access
The volatile declaration has little to do with atomicity. All
primitive variable types except "long" and "double" are always
processed atomically, or "all bits in parallel", whether or not they
are volatile. It is true that adding "volatile" will make long and
double variables be accessed atomically when they would not normally
be, but that is not the primary intent of "volatile".
> without caching the value elsewhere (like in a JVM register).
That is what "volatile" does: force all accesses to the variable to
operate directly on the shared memory. Reads cannot rely on values
held in registers, CPU caches, motherboard caches, etc., and they
can't be optimized. They have to go all the way to the main memory and
get the latest value every time. Similarly, values being written must
be written to the shared memory immediately and in the expected
sequence, not just held in a register or a cache perhaps to be written
at a more convenient time.
"Volatile" can be useful when there is only one thread writing a
particular variable. If the variable is a primitive and not a long or
double, using "volatile" removes the need for locking. It also removes
the requirement for memory barriers, although some JVM implementations
might use memory barriers in their implementations of getfield,
putfield, getstatic, and putstatic anyway.