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

Doug Lea dl at cs.oswego.edu
Thu Jul 6 08:25:19 EDT 2017


On 07/06/2017 05:13 AM, Andrew Haley 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.
> 
> 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.

Right. Hoping not add confusion, the underlying issues also arise in
upcoming Value Types. (https://wiki.openjdk.java.net/display/valhalla/Main)

These "actual" value types will (like primitives) use "==" for
(possibly multiple component) equality.
VarHandles for atomic operations will need to use some form of locking.
Possibilities (not yet fully implemented) include some combination of
(1) just using a global lock for all values (2) using a pool of locks
(e.g., hashed on containing object identityHashCode), and/or
(3) using native hardware transactions on platforms supporting them
(e.g., recent x86). Plus potential specializations for non-SC VarHandle
operations (e.g.,  seqlocks for getAcquire).

In principle, you could apply most of these (no HTM) for current uses of
value-based classes.

-Doug





> 
> There are some things we know, however, despite the documentation of
> "Value-based Classes".  For any reference r, r == r.  If r refers to a
> value-based class, r.equals(r) will always return true.  I don't think
> that anything which appears in that section can overrule these basic
> properties.  Because of this, you can keep a pool of Instant
> instances and intern them, and then, I believe, a reference CAS will
> work.  But you'll need a synchronized factory to do that.
> 
> Obviously a CAS-able timestamp would be a nice thing to have, but
> java.time.Instant is not the timestamp you're looking for.
> 



More information about the Concurrency-interest mailing list