I got some questions about AtomicReference.compareAndSet() method, according to the doc, it said:
Atomically sets the value to the given updated value if the current value == the expected value.
As far as I understand, the ==
operator is comparing the address of two objects, if so how will it work in examples like this
private AtomicReference<AccessStatistics> stats =
new AtomicReference<AccessStatistics>(new AccessStatistics(0, 0));
public void incrementPageCount(boolean wasError) {
AccessStatistics prev, newValue;
do {
prev = stats.get();
int noPages = prev.getNoPages() + 1;
int noErrors = prev.getNoErrors;
if (wasError) {
noErrors++;
}
newValue = new AccessStatistics(noPages, noErrors);
} while (!stats.compareAndSet(prev, newValue));
}
In this code snippet, how does jvm know which fields of AccessStatistics
are to be compared in the compareAndSet()
? In fact I'm just wondering how is this whole strategy working given java doesn't allow to override ==
at all?
Thanks for any comments!
It doesn't. It is not comparing the fields in the object. It is just comparing the reference of the object which is what the documentation says. That's just how the
AtomicReference
class works. As you mention from the javadocs, it uses==
and not theequals()
method.All of the
Atomic*
classes have similar functions. It allows you to atomically set values while being sure that another thread doesn't overwrite your value. WithcompareAndSet(...)
you have to specify the current object reference to ensure you are updating as expected.In your code snippet, it is trying to add to an immutable access-statistics object. So it gets the current value, adds to it, and then stores the new statistic to the reference. If another thread stored its stats between that time, then the
compareAndSet
will return false and it loops around and tries again. This solves race conditions without having to have asynchronized
block.