Reputation: 47
In java 17, AtomicReference
has the compareAndExchange
method which is like compareAndSet
, but instead of returning a boolean, it returns the value right before the atomic action. I need that to implement a custom concurrent structure.
Due to limitations on the project, I have to use only Java 8 features. Some digging revealed VarHandle
which has compareAndExchange
. However, VarHandle
requires Java 9.
Therefore, it seems that I have to implement the compareAndExchange
myself. But how to do so efficiently with the existing methods? (And what about the compareAndExchangeWeak
version?)
(I cannot rely on any third-party libraries, BTW)
Upvotes: 1
Views: 601
Reputation: 718758
This is close but has an observable difference in at least one case:
V witness = ref.get();
if (ref.compareAndSet(oldValue, newValue)) {
return oldValue;
} else {
return witness;
}
If witness != oldValue
, the witness
value is not necessarily the correct value of the reference at the instant we do the compare-and-set.
However, it is not clear whether that value would be useful anyway ... so "close but not exactly right" may be sufficient. With a 100% correct compareAndExchange
, the returned witness
doesn't tell the caller what the state of the reference is now. Another thread could have changed the reference by the time that caller tries to use the returned value.
For example, this could return a value that matches oldValue
without having done the store. e.g. if multiple threads run this simultaneously with the same oldValue
when ref
has that value, they can all loads witness = oldValue
, but only one will succeed the CAS. So you can't safely use the return value to determine whether your CAS "won the race" to update ref
. You need to keep to bool
return value from compareAndSet
for that.
I don't think it is possible to do an exact emulation of compareAndExchange
without using locks ... which would largely defeat the purpose of using an AtomicReference
.
Upvotes: 6