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

Alex Otenko oleksandr.otenko at gmail.com
Thu May 25 04:30:08 EDT 2017

Yes, your quote is a rather weak guarantee. That’s a shame.

The API should provide strong guarantees. Those who want them weaker, should do their own checks. eg expected == stored value is easy to test to skip compareAndSet call, but is not easy (if possible at all!) to enforce a strong guarantee, if the API is unable to provide one: how do I make sure the edge exists, without ruining the value?

Besides, the old implementation of getAndSet() used to invoke compareAndSet() inside. That’s another very subtle gotcha.


> On 25 May 2017, at 09:16, Gil Tene <gil at azul.com> wrote:
>> On May 25, 2017, at 12:35 AM, Alex Otenko <oleksandr.otenko at gmail.com> wrote:
>> This is a bad idea.
>> Now there is no guarantee that the synchronizes-with edge exists.
> The current Java 9 specification (in the JavaDoc) of AtomicReference.updateAndGet() doesn't say there is such an edge (the Java 8 one did, but the current Java 9 one doesn't). So this is valid with the current spec'ed behavior. The spec is probably wrong and should be changed to document the expected memory semantics in any case, and depending on what those are, the suggested optimization will either be ok or wrong to do.
>> Alex
>>> On 24 May 2017, at 22:50, 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
>> _______________________________________________
>> 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