AtomicReference中compareAndSet和weakCompareAndSet之间的区别是什么?

Eri*_*ric 12 java atomicreference

源代码是一回事.

public final boolean compareAndSet(V expect, V update) {
    return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}

public final boolean weakCompareAndSet(V expect, V update) {
    return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
Run Code Online (Sandbox Code Playgroud)

重点是什么?

the*_*472 8

x86具有用于实现CAS的LOCK CMPXCHG指令,该指令是原子的,并提供(近)最大的顺序保证,您无法真正削弱它。

但是在其他平台(例如PowerPC或ARM)上,CAS是由若干条指令序列实现的,这些指令将LL / SC和内存屏障作为单独的构建块提供。这为您的CAS在订购和故障保证方面的强大程度提供了一定的回旋余地。相反,这意味着全功能CAS比某些并发算法所需的指令序列成本更高。

因此,weakcas可让您在此类平台上进行一些权衡。

Javadoc对于弱化排序的确切含义是含糊的,因为当前无法用Java内存模型来表示它。在将来与C ++ 11内存模型更紧密地结合在一起时,可能会对此进行修订。

JSR-133 Cookbook的Multiprocessor一章中的表格概述了平台之间的差异。

  • 很好的答案。 (2认同)

Ste*_*n C 7

weakCompareAndSet javadoc的解释是这样的:

如果当前值==期望值,则以原子方式将该值设置为给定的更新值。

可能会虚假地失败,并且不提供排序保证,因此很少是compareAndSet的适当替代方法。

简而言之,javadoc说该weak版本是(或曾经是)提供“较弱”保证的版本。

现在,正如您所观察到的,这两种方法的当前实现是相同的。根据Grepcode网站上的源代码,从Java 6到Java 8(至少)都是如此。

因此,我推测这两种方法的实现方式之一是:

  • 最初是不同的,但由于对以下实施的全面检查而变得相同Unsafe

    • 为了方便起见(例如,节省实施工作量
    • 因为所谓的“弱”版本的性能,或者
    • 因为“弱”版本有问题;例如,很难正确使用。
  • 最初是相同的,并且指定了差异(但未实现),因为设计人员认为可能存在性能优势。

最后的解释是不可能的。如果最初以相同的方式实现两种方法,则将它们重新实现为不同的方法可能会破坏先前存在的代码。即使对于,这也是一个坏主意Unsafe


@assylias / @ Stefan Gobel评论了另一种解释。基本上,我们在源代码中看到的“相同代码”实际上可以由JIT编译器重写,以为这两种方法提供不同的机器代码。

这当然是合理的。对于某些(非本机)方法调用,JIT编译器确实具有特殊情况的代码生成:所谓的“内部”。

  • @assylias内部函数 (2认同)