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

时间:2016-04-05 13:39:01

标签: 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);
}

有什么意义?

4 个答案:

答案 0 :(得分:4)

weakCompareAndSet javadoc解释了这一点:

  

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

     

虚假失败并且不提供排序保证,因此很少是compareAndSet的合适替代方案。

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

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

所以我猜测这两种方法的实现是:

  • 最初不同,但由于对Unsafe的实施进行了彻底检查,结果相同:

    • 为方便起见(例如节省实施工作)
    • 因为假设“弱”版本的表现,或
    • 因为“弱”版本存在问题;例如它太难以正确使用。
  • 最初是相同的,并且指定了差异(但没有实现),因为设计师认为可能存在性能优势。

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

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

这当然是合理的。 JIT编译器确实为某些(非本机)方法调用生成了特殊的案例代码:所谓的“内在函数”。

答案 1 :(得分:4)

x86只是为了这个目的而拥有LOCK CMPXCHG指令,它是原子的并提供(近 - )最大排序保证,你不能真正削弱它。

但是在像ARM这样的其他平台上,它实际上是作为几个指令的序列实现的,涉及LL/SC和可能的内存障碍。这提供了一些摆动空间CAS在订购和故障保证方面的强大程度。相反,它意味着全强度CAS是一种比一些并发算法所要求的更昂贵的指令序列。

所以weakcas允许你在这样的平台上做出一些权衡。

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

JSR-133 Cookbook的多处理器章节中的表格概述了平台的不同之处。

答案 2 :(得分:0)

同样来自Java文档,看起来其他答案也错过了这一点:

  

原子类还支持方法weakCompareAndSet,该方法具有   适用范围有限。在某些平台上,弱版本可能更多   在正常情况下比compareAndSet高效,但不同之处在于   任何给定的weakCompareAndSet方法调用都可能返回false   虚假地(即没有明显的原因)。错误的回报意味着   仅在需要时可以重试该操作,具体取决于   确保当变量持有时重复调用   ExpectedValue,并且没有其他线程也在尝试设置   变量最终将成功。 (这种虚假的故障可能会   例如是由于与内存无关的内存争用效果   预期值和当前值是否相等。)此外   weakCompareAndSet不提供以下排序保证   通常需要进行同步控制。但是,方法可能是   在更新计数器和统计信息时非常有用   与其他事件无关-在程序订购之前。当一个   线程看到由引起的原子变量更新   weakCompareAndSet,它不一定会看到其他任何更新   在weakCompareAndSet之前发生的变量。这可能是   例如在更新效果统计信息时可以接受,但是   否则很少。

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/package-summary.html#weakCompareAndSet

答案 3 :(得分:-1)

从功能上讲,两者都是一样的。主要区别在于weakAtomicCompareAndSet可以虚假地失败(see oracle documentation)并且不提供订购保证

建议使用atomicCompareAndSet而不是弱版本