Java volatile 引用与 AtomicReference

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/281132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:27:12  来源:igfitidea点击:

Java volatile reference vs. AtomicReference

javaconcurrency

提问by auramo

Is there any difference between a volatileObject reference and AtomicReferencein case I would just use get()and set()-methods from AtomicReference?

volatile对象引用和AtomicReference万一我只使用get()set()-methods from之间有什么区别AtomicReference吗?

采纳答案by pgras

Short answer is: No.

简短的回答是:不。

From the java.util.concurrent.atomicpackage documentation. To quote:

java.util.concurrent.atomic包文档。报价:

The memory effects for accesses and updates of atomics generally follow the rules for volatiles:

  • gethas the memory effects of reading a volatilevariable.
  • sethas the memory effects of writing (assigning) a volatilevariable.

原子的访问和更新的记忆效应一般遵循 volatile 的规则:

  • get具有读取volatile变量的记忆效应。
  • set具有写入(分配)volatile变量的记忆效应。

By the way, that documentation is very good and everything is explained.

顺便说一句,该文档非常好,并且解释了所有内容。



AtomicReference::lazySetis a newer (Java 6+) operation introduced that has semantics unachievable through volatilevariables. See this postfor more information.

AtomicReference::lazySet是一种较新的(Java 6+)操作,它具有通过volatile变量无法实现的语义。有关更多信息,请参阅此帖子

回答by Avi

No, there is not.

不,那里没有。

The additional power provided by AtomicReference is the compareAndSet() method and friends. If you do not need those methods, a volatile reference provides the same semantics as AtomicReference.set() and .get().

AtomicReference 提供的额外功能是 compareAndSet() 方法和朋友。如果您不需要这些方法,可变引用提供与 AtomicReference.set() 和 .get() 相同的语义。

回答by Peter Lawrey

AtomicReferenceprovides additional functionality which a plain volatile variable does not provide. As you have read the API Javadoc you will know this, but it also provides a lock which can be useful for some operations.

AtomicReference提供普通 volatile 变量不提供的附加功能。当您阅读 API Javadoc 时,您就会知道这一点,但它也提供了一个对某些操作很有用的锁。

However, unless you need this additional functionality I suggest you use a plain volatilefield.

但是,除非您需要此附加功能,否则我建议您使用普通volatile字段。

回答by endless

JDK source codeis one of the best ways to answers confusions like this. If you look at the code in AtomicReference, it uses a volatie variable for object storage.

JDK 源代码是解决此类混淆的最佳方法之一。如果您查看 AtomicReference 中的代码,它使用 volatie 变量进行对象存储。

private volatile V value;

So, obviously if you are going to just use get() and set() on AtomicReference it is like using a volatile variable. But as other readers commented, AtomicReference provides additional CAS semantics. So, first decide if you want CAS semantics or not, and if you do only then use AtomicReference.

所以,很明显,如果你只在 AtomicReference 上使用 get() 和 set() ,它就像使用一个 volatile 变量。但正如其他读者评论的那样,AtomicReference 提供了额外的 CAS 语义。因此,首先决定您是否需要 CAS 语义,如果您只需要使用 AtomicReference。

回答by Nitsan Wakart

There are several differences and tradeoffs:

有几个区别和权衡:

  1. Using an AtomicReferenceget/set has the same JMM semanticsas a volatile field(as the javadoc states), but the AtomicReferenceis a wrapper around a reference, so any access to the field involves a further pointer chase.

  2. The memory footprint is multiplied(assuming a compressed OOPs environment, which is true for most VMs):

    • volatile ref = 4b
    • AtomicReference= 4b + 16b (12b object header + 4b ref field)
  3. AtomicReferenceoffers a richer API than a volatile reference. You can regain the API for the volatile reference by using an AtomicFieldUpdater, or with Java 9 a VarHandle. You can also reach straight for sun.misc.Unsafeif you like running with scissors. AtomicReferenceitself is implemented using Unsafe.

  1. 使用AtomicReferenceget/set 具有与volatile 字段相同的JMM 语义(如 javadoc 所述),但它AtomicReference是一个引用的包装器,因此对该字段的任何访问都涉及进一步的指针追逐

  2. 内存占用乘以(假设压缩糟糕的环境,这是真实的大多数虚拟机):

    • 易失性参考 = 4b
    • AtomicReference= 4b + 16b(12b 对象头 + 4b ref 字段)
  3. AtomicReference提供比 volatile 引用更丰富的 API。您可以使用AtomicFieldUpdater或 Java 9 a重新获得易失性引用的 API VarHandlesun.misc.Unsafe如果你喜欢用剪刀跑步,你也可以直接伸手去拿。AtomicReference本身是使用Unsafe.

So, when is it good to choose one over the other:

那么,什么时候选择一个比较好:

  • Only need get/set? Stick with a volatile field, simplest solution and lowest overhead.
  • Need the extra functionality? If this is a performance(speed/memory overhead) sensitive part of your code make a choice between AtomicReference/AtomicFieldUpdater/Unsafewhere you tend to pay in readability and risk for your performance gain. If this not a sensitive area just go for AtomicReference. Library writers typically use a mix of these methods depending on targeted JDKs, expected API restrictions, memory constraints and so on.
  • 只需要获取/设置?坚持使用 volatile 字段、最简单的解决方案和最低的开销。
  • 需要额外的功能吗?如果这是一个性能(速度/内存开销)代码的敏感部分之间做出一个选择AtomicReference/ AtomicFieldUpdater/Unsafe在那里你会在可读性和风险支付您的性能增益。如果这不是一个敏感区域就去AtomicReference。库编写者通常根据目标 JDK、预期的 API 限制、内存限制等混合使用这些方法。