简体   繁体   English

引用赋值是原子的,为什么要使用AtomicReference

[英]Reference assignment is atomic so why use AtomicReference

I have simple general question about AtomicReference. 我有一个简单的关于AtomicReference的一般问题。

Why use AtomicReference if reference assignment is atomic in java? 为什么使用AtomicReference,如果引用赋值在java中是原子的?

Also I would like to ask if reference assigment is atomic in 64-bit VMs? 另外我想问一下64位虚拟机中的引用分配是否是原子的?

Do we need volatile to have reference assigment atomic? 我们是否需要挥发性以使参考分配原子?

Why use AtomicReference if reference assignment is atomic in java? 为什么使用AtomicReference,如果引用赋值在java中是原子的?

You need it when the decision on which the creation of the new value is based can depend on the previous value of the reference. 当新值的创建所依据的决定取决于引用的先前值时,您需要它。 For instance when implementing some LinkedList like data structure you wan't to set the head to a new node which refers to the previous node. 例如,当实现某些LinkedList之类的数据结构时,您不想将头部设置为引用前一个节点的新节点。 In the time between reading the previous node and setting head to the new one some other thread could have concurrently updated the head reference's value. 在读取前一个节点和将头设置为新节点之间的时间内,某个其他线程可以同时更新头参考值。 If our thread would not be aware of this change, it would go lost. 如果我们的线程不会意识到这种变化,它就会丢失。

Do we need volatile to have reference assigment atomic? 我们是否需要挥发性以使参考分配原子?

The operation itself would be performed atomic on the CPU core executing it but there are no guarantees that threads on other cores will be aware of it on the next read. 操作本身将在执行它的CPU内核上执行原子操作,但不能保证其他内核上的线程在下次读取时会知道它。

My previous answer was incorrect, as explained in the comment by juancn: 我之前的回答是不正确的,正如juancn的评论中所解释的那样:

That's the difference between Atomic* classes and volatile access. 这是Atomic*类和易失性访问之间的区别。 Reference assignment is atomic only in the sense that no word tearing can occur, but there's no visibility or reordering guarantees. 参考分配只是在没有发生单词撕裂的意义上是原子的,但是没有可见性或重新排序保证。 Java guarantees atomic writes in this restricted sense for all primitive types and references but not for long/double (although in 64bit VMs I think they're always atomic). Java保证在所有基本类型和引用的限制意义上的原子写入,但不保证long / double的原子写入(尽管在64位VM中我认为它们总是原子的)。

Previous answer 以前的答案

It is necessary, mainly for compareAndSet and getAndSet methods. 这是必要的,主要用于compareAndSetgetAndSet方法。 You cannot do this atomically otherwise (2 operations are needed). 否则你不能原子地做这个(需要2个操作)。

The reason is that even though the reference is atomic, it is atomic in a very narrow sense. 原因是即使引用是原子的,它在非常狭窄的意义上也是原子的。

If a thread writes a non volatile reference, what is guaranteed is that other threads will see the whole write or not see it at all (no word tearing/garbage). 如果一个线程写了一个非易失性引用,那么保证的是其他线程将看到整个写入或根本看不到它 (没有单词撕裂/垃圾)。

But at no point it is guaranteed that any other thread will ever see it nor that they will be seen in the same order. 但绝不保证任何其他线程都能看到它 ,也不会以相同的顺序看到它们。

An AtomicReference provides much stronger guarantees (besides the CAS operations), essentially they behave like volatile: AtomicReference提供了更强大的保证(除了CAS操作),基本上它们的行为类似于volatile:

  • Any writes that happened in thread A before a volatile write are visible in thread B after a subsequent volatile read of that variable 在线程B中发生的任何写入在易失性写入之前在线程B中在该变量的后续易失性读取之后可见
  • volatile operations cannot be reordered 易失性操作无法重新排序

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM