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

Gregg Wonderly gergg at cox.net
Wed May 24 18:21:19 EDT 2017


One of the things that ends up happening, is that people to start trying to do the optimizations that you are doing here, in their own code, knowing what other fences are guaranteed to be happening.  As soon as you make this a conditional fence, you force the user to always use their own fence if they were relying on this fence, and now they have two fences that are dropped when they only ever needed one.  And, if you force them to wrap this operation into an object that can mediate the details of whether or not a fence was actually encountered in the actions of the API, they are recreating exactly the logic you have in your code, and then they will simply be prepared to just go ahead and skip out on providing the JRE provided implementation because it is now a barrier to simple programming models that have simple, dependable behavior.

At some level, there is only so many optimizations that should be done behind the users back.  Surprises like this with disappearing fences will suddenly break a lot of software for nearly unexplainable reasons without deep dives into implementation details and other nuances of behavior which just used to work because the fence was always there.

To put this another way, if the runtime environment is ever going to provide fences than the circumstance of doing that or not doing that should be completely controllable by the developer so that there are no surprises and no change in correctness happening because of things like this going on behind the scenes.

Gregg

> On May 24, 2017, at 4:50 PM, Mike Duigou <openjdk at duigou.org> wrote:
> 
> That's my view of this optimization as well; the writes that occur do change but only in ways that nobody should be able to rely upon. Assuming the proposed change to getAndUpdate seemed reasonable to folks I planned to next suggest:
> 
> replace:
> 
> public final boolean compareAndSet(V expect, V update) {
>   return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
> }
> 
> with:
> 
> public final boolean compareAndSet(V expect, V update) {
>    return expect != update
>       ? unsafe.compareAndSwapObject(this, valueOffset, expect, update)
>       : expect != value ? false : true;
> }
> 
> For both the proposed updateAndGet and compareAndSet the goal is to avoid expensive volatile writes when the value is not actually changing.
> 
> Mike
> 
> On 2017-05-24 12:38, Justin Sampson wrote:
>> Andrew Haley wrote:
>>> Mike Duigou wrote:
>>> > I find that I write a lot of update functions which only occasionally
>>> > change the value. For these cases I wonder if it would be reasonable to
>>> > skip the update if the value of next is unchanged from previous.
>>> I don't think so, because the update has the effect of a volatile
>>> write. If you skip the update you lose the happens-before ordering
>>> of that write.
>> That's strictly true (the memory barriers come out different), but no
>> algorithm could actually rely on the difference. The reading thread can't
>> tell if it's reading after the write (and therefore can depend on the
>> happens-before) or reading before the write (and therefore cannot), since
>> it sees the same value in either case.
>> This kind of optimization is already done in some places in the JDK, such
>> as AtomicStampedReference and AtomicMarkableReference, both of which skip
>> the write if the current value is already equal to the new value in set(),
>> compareAndSet(), etc.
>> Cheers,
>> Justin
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest



More information about the Concurrency-interest mailing list