源代码是一回事。
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);
}
有什么意义?
答案 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之前发生的变量。这可能是 例如在更新效果统计信息时可以接受,但是 否则很少。
答案 3 :(得分:-1)
从功能上讲,两者都是一样的。主要区别在于weakAtomicCompareAndSet可以虚假地失败(see oracle documentation)并且不提供订购保证
建议使用atomicCompareAndSet而不是弱版本