我对 AtomicReference 有一个简单的一般性问题。
如果引用分配在 java 中是原子的,为什么要使用 AtomicReference?
另外我想问一下在 64 位 VM 中引用分配是否是原子的?
我们是否需要 volatile 才能拥有原子的参考分配?
我对 AtomicReference 有一个简单的一般性问题。
如果引用分配在 java 中是原子的,为什么要使用 AtomicReference?
另外我想问一下在 64 位 VM 中引用分配是否是原子的?
我们是否需要 volatile 才能拥有原子的参考分配?
如果引用分配在 java 中是原子的,为什么要使用 AtomicReference?
当创建新值的决策依赖于引用的先前值时,您需要它。例如,在实现一些类似 LinkedList 的数据结构时,您不想将头部设置为引用前一个节点的新节点。在读取前一个节点和将 head 设置为新节点之间的时间里,其他一些线程可能同时更新了 head 引用的值。如果我们的线程不知道这个变化,它就会丢失。
我们是否需要 volatile 才能拥有原子的参考分配?
操作本身将在执行它的 CPU 内核上以原子方式执行,但不能保证其他内核上的线程在下一次读取时会知道它。
我之前的回答是不正确的,正如 juancn 的评论中所解释的那样:
Atomic*
这就是类和易失性访问之间的区别。仅在不会发生单词撕裂的意义上,引用分配是原子的,但没有可见性或重新排序保证。Java 保证所有原始类型和引用在这种受限意义上的原子写入,但不保证 long/double(尽管在 64 位 VM 中我认为它们总是原子的)。
上一个答案
它是必要的,主要用于compareAndSet
和getAndSet
方法。否则,您不能以原子方式执行此操作(需要 2 次操作)。
原因是即使引用是原子的,但它在非常狭义的意义上是原子的。
如果一个线程写入一个非易失性引用,则可以保证其他线程将看到整个写入或根本看不到它(没有字撕裂/垃圾)。
但在任何时候都不能保证任何其他线程都会看到它,也不能保证它们会以相同的顺序被看到。
AnAtomicReference
提供了更强大的保证(除了 CAS 操作),本质上它们的行为类似于 volatile: