28

我对 AtomicReference 有一个简单的一般性问题。

如果引用分配在 java 中是原子的,为什么要使用 AtomicReference?

另外我想问一下在 64 位 VM 中引用分配是否是原子的?

我们是否需要 volatile 才能拥有原子的参考分配?

4

3 回答 3

24

如果引用分配在 java 中是原子的,为什么要使用 AtomicReference?

当创建新值的决策依赖于引用的先前值时,您需要它。例如,在实现一些类似 LinkedList 的数据结构时,您不想将头部设置为引用前一个节点的新节点。在读取前一个节点和将 head 设置为新节点之间的时间里,其他一些线程可能同时更新了 head 引用的值。如果我们的线程不知道这个变化,它就会丢失。

我们是否需要 volatile 才能拥有原子的参考分配?

操作本身将在执行它的 CPU 内核上以原子方式执行,但不能保证其他内核上的线程在下一次读取时会知道它。

于 2013-03-04T12:14:48.203 回答
21

我之前的回答是不正确的,正如 juancn 的评论中所解释的那样:

Atomic*这就是类和易失性访问之间的区别。仅在不会发生单词撕裂的意义上,引用分配是原子的,但没有可见性或重新排序保证。Java 保证所有原始类型和引用在这种受限意义上的原子写入,但不保证 long/double(尽管在 64 位 VM 中我认为它们总是原子的)。

上一个答案

它是必要的,主要用于compareAndSetgetAndSet方法。否则,您不能以原子方式执行此操作(需要 2 次操作)。

于 2013-03-04T07:16:37.640 回答
8

原因是即使引用是原子的,但它在非常狭义的意义上是原子的。

如果一个线程写入一个非易失性引用,则可以保证其他线程将看到整个写入或根本看不到它(没有字撕裂/垃圾)。

但在任何时候都不能保证任何其他线程都会看到它,也不能保证它们会以相同的顺序被看到。

AnAtomicReference提供了更强大的保证(除了 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
  • volatile operations cannot be reordered
于 2017-09-07T17:54:09.837 回答