[concurrency-interest] Volatile / Sychronized?
jmanson at cs.umd.edu
Tue Dec 19 23:50:17 EST 2006
First Last wrote:
> Thanks very much for the answers.
>>> Question #1:
> Ok, so the pitfall is to assume volatile alone is enough, rather
> you must use volatile along with a write and a read to that volatile
> field - in that order.
> I can't really think of an example of what this would like, should someone
> code the mistake, unless they just removed the check of the volatile flag
> completely before reading x because they thought the write was enough,
> which kind of seems silly.
A lot of people (especially OS types) are used to having a memory
barrier operation available to them. The point is, more or less, that
accesses to volatile fields do NOT behave as memory barriers.
>>> Question #2:
> Ok, so this just makes sure there is only one object instantiation
> of Helper, and makes sure there is only assignment. Nothing at
> all to do with a partially completed constructor. I see.
> Explicitly synchronizing a write to a volatile field seems to be silly,
> to me now unless I am synchronizing some other action around
> the write as in your DCL example.
Exactly -- the reason to use synchronized and the reason to use volatile
have nothing to do with each other.
>>> Question #3:
> Just to be clear, I can rely on the runtime and the compiler not to
> reorder anything oddly. The object will be fully constructed before
> the assignment to the volatile makes anything visible to other threads.
Being extra-special careful -- it will only be visible to other threads
that read the volatile and see the value assigned to it. You can't
think about it as the runtime and compiler not reordering things oddly,
because that can come back to get you:
(volatile v = false, normal b = false, normal x = 0)
x = 1;
v = true;
b = true;
r1 = x; // sees 1;
r2 = x; // can see 1 or 0
If you thought about it in terms of "the compiler not reordering
anything oddly", you might imagine that the read in Thread 3 was
guaranteed to see 1. But you would be wrong.
>>> Question #4:
> Is it fair to say the only reason to use Atomic* classes is for CAS
The AtomicX, where <X extends Number>, classes have atomic increment and
decrement operations. One common mistake with volatiles is the idea that:
volatile int v;
is guaranteed to happen all at once, and that no other thread can update
v while it is occurring. This is wrong.
The AtomicXArray classes have atomically accessed elements. volatile
arrays do not have special memory semantics for reads and writes of
their elements -- only the reference to the array is atomic.
There is probably a fair bit that I am forgetting. The javadoc for
java.util.concurrent.atomic goes into it in detail.
More information about the Concurrency-interest