0

根据文档,我对 AtomicReference.compareAndSet() 方法有一些疑问,它说:

如果当前值 == 预期值,则自动将值设置为给定的更新值。

据我了解,==运算符正在比较两个对象的地址,如果是这样,它将如何在这样的示例中工作

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));
}

在这段代码片段中,jvm 如何知道AccessStatistics要在compareAndSet()? 事实上,我只是想知道这整个策略是如何工作的,因为 java 根本不允许覆盖==?感谢您的任何评论!

4

2 回答 2

5

jvm如何知道要在compareAndSet()中比较AccessStatistics的哪些字段?

它没有。它不是比较对象中的字段。它只是比较文档所说的对象的引用。这就是AtomicReference课堂的运作方式。正如您在javadocs中提到的那样,它使用==而不是equals()方法。

如果当前值 == 预期值,则自动将值设置为给定的更新值。

所有的Atomic*类都有类似的功能。它允许您以原子方式设置值,同时确保另一个线程不会覆盖您的值。您必须指定当前对象引用以compareAndSet(...)确保按预期进行更新。

在您的代码片段中,它试图添加到不可变的访问统计对象。所以它获取当前值,添加到它,然后将新的统计信息存储到引用中。如果另一个线程在那段时间之间存储了它的统计信息,那么compareAndSet它将返回 false 并循环并再次尝试。这解决了竞争条件,而无需synchronized阻塞。

于 2012-07-27T16:14:18.737 回答
2

JVM 根本不比较字段。它只是比较它是否是同一个引用,内存中的同一个指针,或者你想调用的任何东西。

于 2012-07-27T16:14:17.877 回答