- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
From the Java AtomicReferenceFieldUpdater
docs :
Note that the guarantees of the
compareAndSet
method in this class are weaker than in other atomic classes. Because this class cannot ensure that all uses of the field are appropriate for purposes of atomic access, it can guarantee atomicity and volatile semantics only with respect to other invocations ofcompareAndSet
andset
.
compareAndSet
一起进行正常的 volatile 写入,但必须使用
set
反而。它没有提到有关
get
的任何内容.
set
之前的写入或
compareAndSet
每个阅读过 volatile 字段的人都可以看到吗?
get
在
AtomicReferenceFieldUpdater
而不是在场上进行 volatile 读取?
The atomicity guarantees for the updater classes are weaker than for the regular atomic classes because you cannot guarantee that the underlying fields will not be modified directly — the compareAndSet and arithmetic methods guarantee atomicity only with respect to other threads using the atomic field updater methods.
最佳答案
如 the package documentation 中所述对于原子(一般来说,不是专门的更新程序):
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.- [...]
compareAndSet
and all other read-and-update operations such asgetAndIncrement
have the memory effects of both reading and writingvolatile
variables.
compareAndSet
试图解决?为什么使用(例如)
atomicInteger.compareAndSet(1,2)
而不是
if(volatileInt == 1) { volatileInt = 2; }
?它并不试图解决并发读取的任何问题,因为这些问题已经由常规
volatile
处理了。 . (“ volatile ”读取或写入与“原子”读取或写入相同。并发读取仅在写入过程中发生,或者语句以某种有问题的方式重新排序或优化时才会出现问题;但是
volatile
已经阻止了这些事情。)
compareAndSet
唯一的问题解决的是,在
volatileInt
在我们读取
volatileInt
之间,其他一些线程可能会并发写入。 (
volatileInt == 1
) 以及当我们写信给它时 (
volatileInt = 2
)。
compareAndSet
通过在此期间锁定任何竞争写入来解决此问题。
AtomicReferenceFieldUpdater
等)的特定情况下同样如此:
volatile
阅读仍然只是桃子。更新者的
compareAndSet
方法的唯一限制是,它们不会像我上面写的那样“锁定任何竞争写入”,而是仅锁定来自
AtomicReferenceFieldUpdater
的同一实例的竞争写入。 ;当您同时更新
volatile
时,它们无法保护您直接字段(或者,就此而言,当您同时使用多个
AtomicReferenceFieldUpdater
来更新相同的
volatile
字段时)。 (顺便说一下,这取决于你如何看待它——
AtomicReference
和它的同类也是如此:如果你以绕过他们自己的 setter 的方式更新他们的字段,他们就无法保护你。不同之处在于
AtomicReference
实际上拥有它的字段,它是
private
,所以没有必要警告你不要以某种方式通过外部手段修改它。)
volatile
具有相同原子性的字段保证不会出现部分/不一致读取、语句被重新排序等。
AtomicReferenceUpdater
的文档说混合不安全compareAndSet
使用 volatile 写入,我相信在典型平台上它实际上是安全的。只有在一般情况下才不安全。我这样说是因为包文档中的以下评论:The specifications of these methods enable implementations to employ efficient machine-level atomic instructions that are available on contemporary processors. However on some platforms, support may entail some form of internal locking. Thus the methods are not strictly guaranteed to be non-blocking -- a thread may block transiently before performing the operation.
AtomicReference.set
简单地使用 volatile 写入,因为 AtomicReference.compareAndSet
使用相对于 volatile 写入是原子的比较和交换操作。 AtomicReferenceUpdater.set
肯定比 AtomicReference.set
更复杂,因为它必须使用类似反射的逻辑来更新另一个对象中的字段,但我认为这是它更复杂的唯一原因。一个典型的实现调用 Unsafe.putObjectVolatile
,这是一个较长名称的 volatile 写入。 compareAndSet
可以通过(或多或少)应用 synchronized
来实现到使用 get
的方法和 set
直截了当。但要让它起作用,set
也必须是 synchronized
,原因在我上面的原始答案中解释过;也就是说,它不能只是一个 volatile 写入,因为它可以修改 compareAndSet
之后的字段。已调用 get
但之前compareAndSet
电话set
. java.util.concurrent.ConcurrentLinkedQueue<E>
,我们发现:private static class Node<E> {
private volatile E item;
private volatile Node<E> next;
private static final AtomicReferenceFieldUpdater<Node, Node> nextUpdater =
AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "next");
private static final AtomicReferenceFieldUpdater<Node, Object> itemUpdater =
AtomicReferenceFieldUpdater.newUpdater(Node.class, Object.class, "item");
Node(E x) { item = x; }
Node(E x, Node<E> n) { item = x; next = n; }
E getItem() { return item; }
boolean casItem(E cmp, E val)
{ return itemUpdater.compareAndSet(this, cmp, val); }
void setItem(E val) { itemUpdater.set(this, val); }
Node<E> getNext() { return next; }
boolean casNext(Node<E> cmp, Node<E> val)
{ return nextUpdater.compareAndSet(this, cmp, val); }
void setNext(Node<E> val) { nextUpdater.set(this, val); }
}
AtomicReferenceFieldUpdater.compareAndSet
进行的。或 AtomicReferenceFieldUpdater.set
— 但 volatile 读取似乎可以自由使用,无需调用 AtomicReferenceFieldUpdater.get
. JDK 1.6 的更高版本改为使用 Unsafe
直接(这发生在 Oracle 的 JDK 1.6.0_27 中),但是 JSR 166 邮件列表上的讨论将这种更改归因于性能考虑,而不是对先前实现的正确性的任何疑虑。AtomicReferenceFieldUpdater.set
的调用。 ;但是不接受我对这一点的解释的人可能不会接受我对另一点的解释,并且可能会争辩说上述代码并不意味着对所有平台都是安全的。 Node
似乎允许 volatile 读取与对 AtomicReferenceFieldUpdater.compareAndSet
的调用同时发生,这是一个私有(private)类(class);而且我没有提供任何证据证明其所有者( ConcurrentLinkedQueue
)实际上在没有自己的预防措施的情况下进行了此类调用。 (虽然我还没有证明这个说法,但我怀疑有人会对此提出异议。)关于java - AtomicReferenceFieldUpdater - 方法 set、get、compareAndSet 语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8262982/
我想自动升级我的引用。例如使用 compareAndSet , getAndSet和其他原子操作。 我来自 C++,所以在 C++ 中我有 volatile关键字和不同的原子内在函数,或 API .
我收到以下错误: Exception in thread "main" java.lang.ClassCastException at java.util.concurrent.atomic.Atom
如果我在某个集合结构中有一个链接节点,我真的不希望它的下一个链接是 AtomicReference(我需要原子 CAS 更新),所以我将其声明为: @volatile var next: Node[A
From the Java AtomicReferenceFieldUpdater docs : Note that the guarantees of the compareAndSet metho
我是一名优秀的程序员,十分优秀!