AtomicStampedReference.compareAndSet逻辑判断与原子性疑问
AtomicStampedReference.compareAndSet 源码分析与问题解答
源码展示
public boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) { Pair<V> current = pair; return expectedReference == current.reference && expectedStamp == current.stamp && ((newReference == current.reference && newStamp == current.stamp) || casPair(current, Pair.of(newReference, newStamp))); }
问题
- 为何该方法要加入
newReference == current.reference && newStamp == current.stamp判断? - 这些多布尔逻辑判断是否具备原子性?
- 若不具备,当判断完
expectedReference == current.reference && expectedStamp == current.stamp后,若其他线程将current.reference修改为newReference且current.stamp修改为newStamp,此时方法会返回true且不执行casPair,但该修改实际由其他线程完成,为何要返回true?
解答
1. 加入该判断的原因
核心是避免无意义的CAS操作。如果当前的引用和戳记已经和要设置的新值完全一致,调用casPair做原子更新纯粹是浪费性能——底层CAS指令是相对重的操作,能省则省。直接返回true就够了,因为目标状态已经达成,没必要多此一举。
2. 布尔逻辑判断的原子性
这些判断不具备原子性。虽然current = pair这一步是原子的(因为pair被volatile修饰,保证可见性和单次读取的原子性),但后面的多个==比较是分步执行的普通内存操作,没有加锁也没有原子指令保护。从拿到current到完成所有布尔判断的间隙,其他线程完全有可能修改pair的值。
3. 该场景返回true的合理性
compareAndSet的核心语义是:只要对象最终处于我期望的新状态,就返回true;否则返回false,而不是“必须由我自己完成修改才返回true”。
举个实际场景:我本来想把状态从A改成B,刚确认当前是A,另一个线程抢先把它改成了B。对我来说,目标已经达成了,不需要再做任何操作,返回true完全符合预期——毕竟我调用这个方法的目的是让对象处于新状态,至于谁完成的修改,并不影响最终结果的有效性。
内容的提问来源于stack exchange,提问作者xllz
相关产品推荐
相关产品推荐

