That's actually the common idiom for performant concurrent code that 
occasionally needs to do something atomic, but usually (the hot case) 
doesn't. Without the first read check, there is a good likelihood 
(depending on how the CPU and prefetchers work for CAS, but very probably) 
that you will run into serious false sharing contention on the line under 
high load on multiple cores, as the CAS will bring the line in exclusive 
and invalidate it in other caches, while the first read check will bring it 
in shared, and the invalidation will only happen if you actually need to 
change the value.

On Saturday, October 5, 2019 at 8:41:26 AM UTC-7, Steven Stewart-Gallus 
wrote:
>
> Couldn't you do a compare and compare and swap? With VarHandles something 
> like
>
> if (ACTION.getOpaque(this) != expected) return false;
> return compareAndExchange(this, expected, newValue) == expected;
>
> Not sure I got this correct
>
> On Saturday, September 14, 2019 at 11:29:00 AM UTC-7, Vitaly Davidovich 
> wrote:
>>
>> Unlike C++, where you can specify mem ordering for failure and success 
>> separately, Java doesn’t allow that.  But, the mem ordering is the same for 
>> failure/success there.  Unfortunately it doesn’t look like the javadocs 
>> mention that, but I recall Doug Lea saying that’s the case on the 
>> concurrency-interest mailing list (btw that’s probably the more appropriate 
>> channel for this Java-centric question).
>>
>> For your case, it seems like an AtomicReference<Runnable> is more 
>> appropriate.  terminate() sets it, then checks the count via a volatile 
>> load (or maybe it can decrement() itself?); if zero, CAS null into the 
>> action field to take/claim the action.  decrement() likewise tries to claim 
>> the action via a CAS.  The snippet you have now would allow for concurrent 
>> action execution, which is likely unsafe/wrong.
>>
>> On Fri, Sep 13, 2019 at 3:08 AM Simone Bordet <simone...@gmail.com> 
>> wrote:
>>
>>> Hi,
>>>
>>> I have an atomic counter that gets incremented and decremented over
>>> time (non monotonically).
>>> At a certain point, I would like to enter a termination protocol where
>>> increments are not possible anymore and I set an action to run if/when
>>> the counter reaches zero.
>>> Trivial when using synchronized/lock, but I'd like to give it a try
>>> without them.
>>>
>>> class A {
>>>   private final AtomicLong counter;
>>>   // Non-volatile
>>>   private Runnable action;
>>>
>>>   void terminate(Runnable action) {
>>>     this.action = action;
>>>     // Volatile write needed here for visibility.
>>>     if (counter.addAndGet(0) == 0) {
>>>       action.run();
>>>     }
>>>   }
>>>
>>>   void decrement() {
>>>     // Volatile read required to see this.action.
>>>     if (counter.decrementAndGet() == 0) {
>>>       Runnable a = this.action;
>>>       if (a != null) {
>>>         a.run()
>>>       }
>>>     }
>>>   }
>>> }
>>>
>>> Is addAndGet(0) a volatile write? Can the write be optimized away?
>>> Similarly (although not relevant for this particular example), a
>>> _failed_ compareAndSet() has the semantic of a volatile write even if
>>> the set part was not done because the compare part failed?
>>>
>>> Thanks!
>>>
>>> -- 
>>> Simone Bordet
>>> ---
>>> Finally, no matter how good the architecture and design are,
>>> to deliver bug-free software with optimal performance and reliability,
>>> the implementation technique must be flawless.   Victoria Livschitz
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "mechanical-sympathy" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to mechanical-sympathy+unsubscr...@googlegroups.com.
>>> To view this discussion on the web, visit 
>>> https://groups.google.com/d/msgid/mechanical-sympathy/CAFWmRJ3qGJ_qqrXmAHNDZ6ro01BQwe8czHZP7b-SoZ%2BrULhJAw%40mail.gmail.com
>>> .
>>>
>> -- 
>> Sent from my phone
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/mechanical-sympathy/bf62a5dc-0c89-44cf-aa36-65f0655d0b3a%40googlegroups.com.

Reply via email to