Search code examples
javaconcurrencyatomicreference

AtomicReference


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!


Solution

  • how does jvm know which fields of AccessStatistics are to be compared in the compareAndSet()?

    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 the equals() method.

    Atomically sets the value to the given updated value if the current value == the expected value.

    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. With compareAndSet(...) 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 a synchronized block.