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

Remi Forax forax at univ-mlv.fr
Thu Jul 6 10:48:54 EDT 2017


----- Mail original -----
> De: "Doug Lea" <dl at cs.oswego.edu>
> À: concurrency-interest at cs.oswego.edu
> Envoyé: Jeudi 6 Juillet 2017 14:25:19
> Objet: Re: [concurrency-interest] Should I avoid compareAndSet with value-based classes?

> 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

Value types have no identity so no identityHashCode.

Another alternative is to force the Value Type to implement an interface that will have a method providing the object that will be used to lock.

interface Lockable {
  Object lock();
}

value class MyValues implements Lockable {
  private final Object lock;
  private final Type1 field1;
  ...

  public Object lock() { return lock; }
}

cheers,
Rémi


More information about the Concurrency-interest mailing list