I'm trying to understand the 'Compare And Swap' operation, briefly called CAS. I found that it has a variant called 'Compare And Set'. They work the same way but the return is different. 'Compare And Swap' returns a value but 'Compare And Set' returns a boolean.
My question is whether they use the same Compare And Exchange (CMPXCHG
for x86) instruction on low-level. Are they both implemented by atomic classes in Java ?
Yes, it's a wrapper that exposes the functionality of x86 lock cmpxchg
or equivalent compare-and-swap instructions / sequences on other ISAs. But Java's old compareAndSet
API only returns the boolean success, not the old value on failure, so there are things it can't quite do.
A recent question, Java 8 impl on Compare And Exchange (Not Compare and Set!) was about emulating Java17 compareAndExchange
(returning the old value) in terms of Java compareAndSet
- it can't be done precisely. You can load a value from near the time of the exchange, but it might end up the same as the "expected" arg to your CAS even if your CAS failed. But if you keep both the boolean and the value you read separately, that's fine for most algorithms.
This situation is like GNU C's old __sync_bool_compare_and_swap
vs. __sync_val_...
for cases where you did want the old value. The latter is more powerful: you can get success/fail from the val
version by comparing the return value yourself. So it's a bit disappointing that Java would provide only the less powerful one from Java 8 until Java 17, although it is the one that a lot of algorithms would be more likely to use.
(GNU C later added __atomic
builtins that match the C++11 API of compare_exchange_weak
with a bool return value and the first arg by reference, updated on CAS failure. So you get either or both, depending on which outputs you bother to actually use.)
Also related: