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

Justin Sampson jsampson at guidewire.com
Sat May 27 13:13:41 EDT 2017


Alex Otenko wrote:

> If whoever mutated z from i to k cannot observe stores that precede z.CAS,
> they won’t attempt to mutate z to j.

In your example, how does that other thread know that it is responsible for mutating z to j? What if it has gone on to other things before z.CAS(i, j) even happens?

> In return can someone explain what the difference is between a
> weakCompareAndSet failing spuriously and compareAndSet not guaranteeing
> volatile store semantics on fail? Why should we weaken the promise, if there
> is already a weak promise to not guarantee visibility on fail?

Spurious failure is more about the read than the write, I think. With spurious failure, you can't even rely on volatile read semantics if the CAS fails, because failure doesn't give any information at all about the current value. Without spurious failure, at the very least you know that the current value != the expected value if the CAS fails.

Consider the following levels of CAS strength, off the top of my head:

1. Volatile read always, volatile write always, no spurious failures.
2. Volatile read always, volatile write only if successful, no spurious failures.
3. Volatile read always, volatile write only if value changed, no spurious failures.
4. Volatile read only if successful, volatile write only if value changed, spurious failures allowed.
5. No volatile read, no volatile write, spurious failures allowed.

In JDK 8, compareAndSet was spec'd as #1 and weakCompareAndSet was spec'd as #5, whereas e.g. AtomicStampedReference's compareAndSet method was actually implemented as #3. In my limited concurrency coding, I don't think I've ever wanted something stronger than #3 or weaker than #4. I will be curious to learn whether any of the CAS versions in JDK 9 match those two particular levels.

Cheers,
Justin



More information about the Concurrency-interest mailing list