[concurrency-interest] Should I avoid compareAndSet with value-based classes?

Andrew Haley aph at redhat.com
Thu Jul 6 07:20:01 EDT 2017

On 06/07/17 11:41, Alex Otenko wrote:
>> On 6 Jul 2017, at 10:13, Andrew Haley <aph at redhat.com> wrote:
>> On 06/07/17 04:59, Michael Hixson wrote:
>>> AtomicReference and VarHandle are specified to use == in compareAndSet
>>> (and related) operations [1].  Using == to compare instances of
>>> value-based classes may lead to "unpredictable results" [2].  Does
>>> this mean I should avoid using compareAndSet with arguments that are
>>> instances of value-based classes?
>>> It seems like the documentation clearly tells me "yes, avoid doing
>>> that" but I'm hoping I misunderstood, or maybe AtomicReference and
>>> VarHandle are exempt somehow.  Otherwise, how do I implement
>>> non-broken compareAndSet and updateAndGet for a java.time.Instant
>>> value for example?
>> java.time.Instant stores times that are longer than a JVM word, so
>> they cannot be CAS'd in a lock-free way unless a factory guarantees
>> that instances which compare equal also have the property of
>> reference equality.  j.t.Instant factories in the Java library are
>> explicitly documented *not* to have this property, so that doesn't
>> help.
> That’s not entirely clear.
> Wouldn’t this loop work:
> volatile j.t.Instant curr = ...
> j.t.Instant next = …
> j.t.Instant tmp = ...
> do {
>   tmp = curr;
>   if (tmp.equal(next)) break;
> } while(!curr.CAS(tmp, next));
> // assume curr is equal to next

Something like that, yes.  But it's going to be evil if there are
several high-frequency writers.  If you're doing all that work in
order to CAS a timestamp, why not use a synchronized block?  It would
at least be less prone to the thundering herd, and we'd generate
pretty decent code for that.  It'd be interesting to compare and
contrast the two approaches for contended and non-contended cases.

>> If you want to be able to CAS a reference to a j.t.Instant, you're
>> going to have to wrap accesses to it in a synchronized block.  This is
>> a direct consequence of the JVM's inability to CAS multi-word objects.
> This is confusing.
> Surely this isn’t talking about CASing a reference? The contents of
> the object can’t be assumed to have any atomicity properties,
> whether it is j.t.Instant or not.

I agree.  I'm trying to look at what the OP actually wants to do: I
assume this is some kind of atomic timestamp, and the OP wants to be
able to CAS an instance of j.u.Instant.

Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671

More information about the Concurrency-interest mailing list