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 > <javascript:>> 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 <javascript:>. >> 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/43729dfa-1e73-4318-b446-e80c81422b6e%40googlegroups.com.