javaconcurrencyvolatileatomicreferencejsr166

AtomicReferenceFieldUpdater - methods set, get, compareAndSet semantics


From the Java AtomicReferenceFieldUpdater docs:

Note that the guarantees of the compareAndSet method in this class are weaker than in other atomic classes. Because this class cannot ensure that all uses of the field are appropriate for purposes of atomic access, it can guarantee atomicity and volatile semantics only with respect to other invocations of compareAndSet and set.

This means I can't do normal volatile writes along with compareAndSet, but have to use set instead. It doesn't mention anything about get.

Does that mean that I can still read volatile fields with the same atomicity guarantees - all writes before the set or compareAndSet are visible to everybody who has read the volatile field being?

Or do I have to use get on the AtomicReferenceFieldUpdater instead of volatile reads on the field?

Please post references if you have them.

Thank you.

EDIT:

From Java Concurrency in Practice, the only thing they say:

The atomicity guarantees for the updater classes are weaker than for the regular atomic classes because you cannot guarantee that the underlying fields will not be modified directly — the compareAndSet and arithmetic methods guarantee atomicity only with respect to other threads using the atomic field updater methods.

Again, no mention of how the other threads are supposed to read these volatile fields.

Also, am I right to assume that "modified directly" is a regular volatile write?


Solution

  • As explained in the package documentation for atomics (in general, not the updaters specifically):

    The memory effects for accesses and updates of atomics generally follow the rules for volatiles, [...]:

    • get has the memory effects of reading a volatile variable.
    • set has the memory effects of writing (assigning) a volatile variable.
    • [...]
    • compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.

    What problem is an atomic's compareAndSet trying to solve? Why use (for example) atomicInteger.compareAndSet(1,2) instead of if(volatileInt == 1) { volatileInt = 2; }? It's not trying to solve any problem with concurrent reads, because those are already taken care of by a regular volatile. (A "volatile" read or write is the same as an "atomic" read or write. A concurrent read would only be a problem if it happened in the middle of a write, or if statements were reordered or optimized in some problematic way; but volatile already prevents those things.) The only problem that compareAndSet solves is that, in the volatileInt approach, some other thread might come in with a concurrent write, between when we read volatileInt (volatileInt == 1) and when we write to it (volatileInt = 2). compareAndSet solves this problem by locking out any competing writes during that time.

    This is equally true in the specific case of the "updaters" (AtomicReferenceFieldUpdater etc.): volatile reads are still just peachy. The updaters' compareAndSet methods' only limitation is that, instead of "locking out any competing writes" as I wrote above, they only lock out competing writes from the same instance of AtomicReferenceFieldUpdater; they can't protect you when you're concurrently updating a volatile field directly (or, for that matter, when you're concurrently using multiple AtomicReferenceFieldUpdaters to update the same volatile field). (Incidentally, depending how you look at it — the same is true of AtomicReference and its kin: if you were to update their fields in a way that bypassed their own setters, they couldn't protect you. The difference is that an AtomicReference actually owns its field, and it's private, so there's no need to warn you against somehow modifying it by external means.)

    So, to answer your question: Yes, you can continue to read volatile fields with the same atomicity guarantees against partial/inconsistent reads, against statements being reordered, etc.


    Edited to add (Dec 6): Anyone who's particularly interested in this subject will probably be interested in the discussion immediately below. I was asked to update the answer to clarify salient points from that discussion:

    Please see the below comments for background on this addendum, and for further discussion.