weakCompareAndSet虚假失败是否因LOCK前缀竞争?强弱CAS机制问询
核心命名疑惑
有人提出weakCompareAndSet被命名为“weak”,是因为强版本的compareAndSet具备happens-before排序特性。我对happens-before的理解是它代表内存一致性,而非顺序执行或强内存排序,但人们常混用这些概念,这让我困惑。
重排序与LOCK前缀的关联疑问
重排序分为编译期和运行期两种,我在思考LOCK前缀与重排序的关联时逻辑不通:如果LOCK前缀触发某种机制,具体形式是怎样的?比如运行期为每个并发访问的while循环内联自旋锁并插入内存屏障?
对happens-before与竞态条件的理解
我认为happens-before特性只是确保能知晓当前动作之前发生的状态,但当前动作在并发场景中未必遵循顺序执行一致性,且动作对应的代码可能已被重排序,这仍会存在竞态条件,且这一切与重排序无关。
假设有两个完全相同的线程,它们的代码可能在到达原子操作点之前就已被重排序,强compareAndSet不会阻止这种重排序,仅能保证类似“失败线程可验证自己到达前的内存状态”的happens-before特性——这既不是重排序控制,也不是执行顺序一致性。
LOCK前缀的重试机制疑问
根据LOCK前缀的特性,当指令尝试获取总线时若发现总线已被锁定,是否不会重试获取,直接返回失败?若属实,那么重试获取的行为并非LOCK前缀的固有特性,而是上层代码的责任。
Java中强弱CAS的实现猜想
Java中强compareAndSet使用LOCK+cmpxchg组合来保证happens-before,这是否意味着当LOCK获取失败时,原生代码会自旋重试,直到获取锁后建立互斥的读写关联?LL/SC似乎是描述该结果行为的抽象,而非实现方式,但我未找到深入的相关文献。
但happens-before并非cmpxchg的固有特性,而是重试自旋的结果;若无重试,指令会直接返回失败,不会提供内存状态的“见证”。
那么是否可以说,强CAS具有争议性是因为它会自旋直到总线释放?而weakCompareAndSet即使预期值匹配也可能失败,这符合我的解读:它仅因遇到总线锁定(竞争)就返回失败,无论内存状态如何,因为它不会重试获取锁。如此是否能认为弱CAS是非争议性的,因为它遇到总线锁定就直接返回?
对weakCompareAndSet使用场景的观察
我观察到Java源码中所有使用weakCompareAndSet的场景,都不是读取true、false、枚举等常量,而是通过高级volatile读取变量,且失败后总会伴随上层自旋锁重试。这意味着当遇到竞争时,通过volatile读取的expected值可直接丢弃,尽早返回至应用层重试,而非在原生层自旋获取LOCK——因为这样的cmpxchg比较必然返回false。
请问我的上述解读是否正确?若有相关文献可供参考,将不胜感激。
内容的提问来源于stack exchange,提问作者Delark

