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)));
}
的AtomicStampedReference
方法的源代码。
为什么使用
newReference == current.reference && newStamp == current.stamp
?这里的多个布尔逻辑判断是原子的吗?如果不是,判断完expectedReference == current.reference && expectedStamp == current.stamp
后,如果其他线程将current.reference
修改为newReference
,将current.stamp
修改为newStamp
,则会返回true
,不执行casPair(current, Pair.of(newReference, newStamp)
。但实际上,这个修改是由其他线程完成的,为什么返回true?
这里重要的部分是第一个声明:
Pair<V> current = pair;
casPair
方法时,您可以看到它交换了整个对,并且Pair
的字段是
final
。
因此,它不会逐个比较值,而是首先获取两个值,然后比较已经获得的值。因此
newReference == current.reference && newStamp == current.stamp
实际上并不直接检查接收器的状态,这在检索 Pair
时已经完成了。
但实际上这个修改是由其他线程完成的,为什么会返回true呢?
这本质上是同一件事。使用
Pair<V> current = pair;
以原子方式检索该值,然后与其进行比较。仅当 expectedReference
、current.reference
和 newReference
(以及 expectedStamp
、current.stamp
和 newStamp
)相对于 Pair<V> current = pair;
检索的对象相同时,才会发生这种情况。
在这种情况下,如果该值已经具有该确切值,则您将将该值设置为新值。在这种情况下,您无需更改值即可获得相同的行为,因为将值设置为自身不会产生任何副作用。如果其他人同时更改了
AtomicStampedReference
,则可以认为该更改是“稍后”发生的。