【问题标题】:Is it necessary to declare an AtomicReference as volatile?是否有必要将 AtomicReference 声明为 volatile?
【发布时间】:2011-08-12 06:45:03
【问题描述】:

所有其他原子对象都一样吗?更容易解释 AtomicInteger 的问题。由于超过 1 个线程正在访问对 myInt 的引用,难道不是一个线程可以看到该对象的注册缓存值,例如 null,除非它也被声明为 volatile?如果不是怎么来的?

【问题讨论】:

  • 我尝试将所有 AtomicReference 字段设为最终字段。您应该避免更改它。

标签: java thread-safety


【解决方案1】:

不仅没有必要,而且实际上在语义上是错误的。 AtomicReference 在自身内部保存“真实”引用,并使用自己的同步结构管理对它的访问。 JVM 自己的同步构造(synchronizedvolatile 等)未使用。 AtomicReference 对象本身不应被视为易失性。如果有的话,请考虑将其设为final

还可以考虑this question - 如果您只需要获取和设置操作,volatile 可以被视为使用 AtomicReference 的替代方法。

【讨论】:

  • 为什么不呢?出于正当的原因,一个并发映射很可能被一个 volatile 字段持有,我不明白为什么这对于“原子”对象不应该是正确的?
  • @Enno:当然,我想你可以编造一个合适的场景。但是,如果您在代码中看到volatile AtomicReference,那几乎肯定不是作者想要的。
  • @skaffman:当然,AtomicReference 本身包含对目标对象的真实引用,但我指的是对这个 AtomicReference 对象的引用。但确实我可以让它最终化,而且它也很有意义。谢谢!
【解决方案2】:

“原子”对象不是不可变的,因此只有在正确发布时它们才应该是线程安全的。例如,当您执行此类操作时,您将需要使用 volatile 关键字。

volatile AtomicInteger counter = // initialize counter

int harvest(){
    AtomicInteger old = counter;
    counter = new AtomicInteger();
    return old.get();
}

如果您从上述代码中删除 volatile,您确实可能会丢失一些增量。根据规范,您还可能获得对未完全构造的 AtomicInteger 对象的引用,从而获得未定义的行为。

那么,您需要将您的原子对象声明为 volatile 吗?答案是视情况而定。只要它们被正确发布,它们就是线程安全的,就像任何其他线程安全的对象一样(不可变对象除外,这是特殊情况)。在大多数情况下,您应该将它们设为最终版本。

【讨论】:

    猜你喜欢
    • 2020-10-11
    • 1970-01-01
    • 2013-03-07
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-12
    相关资源
    最近更新 更多