[concurrency-interest] AtomicReference.updateAndGet() mandatory updating?

Mike Duigou openjdk at duigou.org
Mon Jun 5 15:40:57 EDT 2017


I am glad that my original question led to such a fruitful discussion. 
With the conclusion that the Java 8 semantics will be preserved as much 
as possible and the Java 9 descriptions (and implementations?) will be 
amended to conform is there interest in pursuing the "optimized" 
write-eliminating versions? For algorithms (most?) that don't rely on 
the CAS write happening for unchanged values elimination of the write 
seems like a sizeable win for functions that rarely change the value.

public static <T> boolean compareAndSetOpt(AtomicReference<T> ref, T 
expect, T update) {
   return expect != update
     ? ref.compareAndSet(expect, update)
     : expect == ref.get();
}

public static <V> V updateAndGetOpt(AtomicReference<V> ref, 
UnaryOperator<V> updateFunction) {
      V prev = ref.get(), next = null;
      for (boolean haveNext = false;;) {
          if (!haveNext)
              next = updateFunction.apply(prev);
          if (compareAndSetOpt(ref, prev, next))
              return next;
          haveNext = (prev == (prev = ref.get()));
      }
}

Typical usage for me is a linked list:

class Foo {
   final AtomicReference<Foo> nextFoo = new AtomicReference<>();

   /**
    * Returns the successor Foo to this Foo creating it if necessary
    *
    * @return the next Foo
   */
   public Foo nextFoo() {
     return nextFoo.updateAndGet(e -> null != e ? e : new Foo());
   }
}

For this usage the value of nextFoo is only ever changed once, from null 
to some Foo the first time nextFoo() is called. Because this particular 
usage is extreme with the value only changing once I am actually using a 
slightly different version of nextFoo() currently:

public Foo nextFoo() {
   Foo next = nextFoo.get();
   return null != next ? next : nextFoo.updateAndGet(e -> null != e ? e : 
new Foo());
}

which optimizes for read at the cost of an extra volatile read for 
update. I have other usages that are more balanced between the update 
function returning the original value or a different value and use the 
original version of nextFoo().


More information about the Concurrency-interest mailing list