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
Java volatile reference vs. AtomicReference
提问by auramo
Is there any difference between a volatile
Object reference and AtomicReference
in 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.atomic
package documentation. To quote:
从java.util.concurrent.atomic
包文档。报价:
The memory effects for accesses and updates of atomics generally follow the rules for volatiles:
get
has the memory effects of reading avolatile
variable.set
has the memory effects of writing (assigning) avolatile
variable.
原子的访问和更新的记忆效应一般遵循 volatile 的规则:
get
具有读取volatile
变量的记忆效应。set
具有写入(分配)volatile
变量的记忆效应。
By the way, that documentation is very good and everything is explained.
顺便说一句,该文档非常好,并且解释了所有内容。
AtomicReference::lazySet
is a newer (Java 6+) operation introduced that has semantics unachievable through volatile
variables. 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
AtomicReference
provides 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 volatile
field.
但是,除非您需要此附加功能,否则我建议您使用普通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:
有几个区别和权衡:
Using an
AtomicReference
get/set has the same JMM semanticsas a volatile field(as the javadoc states), but theAtomicReference
is a wrapper around a reference, so any access to the field involves a further pointer chase.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)
AtomicReference
offers a richer API than a volatile reference. You can regain the API for the volatile reference by using anAtomicFieldUpdater
, or with Java 9 aVarHandle
. You can also reach straight forsun.misc.Unsafe
if you like running with scissors.AtomicReference
itself is implemented usingUnsafe
.
使用
AtomicReference
get/set 具有与volatile 字段相同的JMM 语义(如 javadoc 所述),但它AtomicReference
是一个引用的包装器,因此对该字段的任何访问都涉及进一步的指针追逐。的内存占用乘以(假设压缩糟糕的环境,这是真实的大多数虚拟机):
- 易失性参考 = 4b
AtomicReference
= 4b + 16b(12b 对象头 + 4b ref 字段)
AtomicReference
提供比 volatile 引用更丰富的 API。您可以使用AtomicFieldUpdater
或 Java 9 a重新获得易失性引用的 APIVarHandle
。sun.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
/Unsafe
where you tend to pay in readability and risk for your performance gain. If this not a sensitive area just go forAtomicReference
. 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 限制、内存限制等混合使用这些方法。