weakCompareAndSet怎么会像compareAndSet一样实现,那么它怎么会虚假地失败呢?

2022-09-01 00:40:34

(请注意,这个问题不是关于CAS的,而是关于“可能虚假地失败”Javadoc)。

Javadoc中这两个方法与类的唯一区别是,weakCompareAndSet包含注释:“可能虚假失败”。AtomicInteger

现在,除非我的眼睛被某种咒语欺骗,否则这两种方法看起来都是一模一样的:

public final boolean compareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

/* ...
 * May fail spuriously.
 */
public final boolean weakCompareAndSet(int expect, int update) {
  return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

所以我意识到“May”并不意味着“必须”,但是为什么我们不开始将它添加到我们的代码库中:

public void doIt() {
    a();
}

/**
 * May fail spuriously
 */
public void weakDoIt() {
    a();
}

我真的对那个弱CompareAndSet()感到困惑,它似乎与compareAndSet()做了同样的事情,但它“可能会虚假地失败”,而另一个则不能。

显然,“弱”和“虚假失败”在某种程度上与“发生之前”排序有关,但我仍然对这两种AtomicInteger(和AtomicLong等)方法感到非常困惑:因为显然它们调用完全相同的不安全.compareAndSwapInt方法

我特别困惑的是,它是在Java 1.5中引入的,所以在Java内存模型更改之后(所以它显然不是“在1.4中虚假失败”的东西,而是其行为更改为“在1.5中不会虚假失败”)。AtomicInteger


答案 1

实现和规范之间是有区别的...

虽然在特定的实现上,提供不同的实现可能没有多大意义,但将来可能在不同硬件上的实现可能想要这样做。此方法是否在 API 中具有其权重是值得商榷的。

此外,这些方法没有定义发生前排序。非版本的行为类似于字段。weakweakvolatile


答案 2

只是为了玩一下,如果你的问题是

如果 weakDoIt 的实现方式与 doIt 完全相同,它怎么会虚假地失败呢?

这是答案!

public void doIt() {
    a();
}

/**
 * May fail spuriously
 */
public void weakDoIt() {
    a();
}

void a(){
    if(Thread.currentThread().getStackTrace()[2].toString().contains("weakDoIt"))
        System.out.println("I will fail spuriously!");
    else System.out.println("I won't fail spuriously!");
}

推荐