【问题标题】:AtomicReference原子参考
【发布时间】:2012-07-27 16:12:35
【问题描述】:

我有一些关于 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));
}

在这段代码sn-p中,jvm如何知道AccessStatistics的哪些字段要在compareAndSet()中进行比较?事实上,我只是想知道这整个策略是如何工作的,因为 java 根本不允许覆盖 ==? 感谢任何 cmets!

【问题讨论】:

标签: java concurrency atomicreference


【解决方案1】:

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

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

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

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

在您的代码 sn-p 中,它试图添加到不可变的访问统计对象。所以它获取当前值,添加到它,然后将新的统计信息存储到引用中。如果另一个线程在此期间存储了 统计信息,则 compareAndSet 将返回 false 并循环并再次尝试。这解决了竞争条件,而不必有 synchronized 块。

【讨论】:

  • 感谢 Gray,话虽如此,AtomicReference 仅用于 IMMUTABLE 对象,这让我更清楚。如果我们只修改 prev 中的一些字段,我会假设这将如何工作......但在这种情况下,它只是覆盖 stats 的值,这将导致 stats 对象指向另一个对象,并且 == 将起作用。
  • @ArrowCen 好吧,没有什么需要不变性,但是是的,正如我在回答中提到的那样,您的代码 sn-p 正在处理看起来像不可变对象的东西。仅供参考:== 也适用于可变对象。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2013-11-19
    • 1970-01-01
    • 2013-04-06
    • 2012-05-17
    • 2012-10-27
    • 2014-05-05
    • 2011-11-17
    • 2011-01-21
    • 1970-01-01
    相关资源
    最近更新 更多