AtomicBoolean 中 getAndSet 和 compareAndSet 的区别

Difference between getAndSet and compareAndSet in AtomicBoolean

线程标题应该是 self-explnatory...我对 AtomicBoolean class:

中的以下方法的规范有点困惑

我的假设是,当在 if 条件中用作布尔子句时,两者会导致相同的行为:

public class Test {
  private AtomicBoolean flag = AtomicBoolean(false);

  public void processSomeAction() {
    if (flag.getAndSet(false)) { // Shouldn't this be similar to flag.compareAndSet(false)
      // process some action
    }
  }
  //...
  private void internalMutatorMethod() {
    // do some staff then update the atomic flag
    flas.set(true);
  }
}

假设我想检索当前标志值并自动更新它,这两种方法不应该产生相同的行为吗?

如果我遗漏了内部差异,我将非常感谢任何有关如何以及何时使用它们的解释。

documentation 很清楚。

  • getAndSet --> "Atomically sets to the given value and returns the previous value."
  • compareAndSet --> "Atomically sets the value to the given updated value if the current value == the expected value."

毫不奇怪,compareAndSet 有两个参数。

在您的具体情况下:

  • if (flag.getAndSet(false)) 仅当其先前值为 true
  • 时才会将 flag 设置为 false
  • 这相当于 if (flag.compareAndSet(true, false))

当我检查实施时,我发现了以下内容

public final boolean getAndSet(boolean newValue) {
    for (;;) {
        boolean current = get();
        if (compareAndSet(current, newValue))
            return current;
    }
}

此外,在检查 javadoc 时,compareAndSet 仅在比较通过时才设置值,而 getAndSet 只需设置值,return 以前的值。

你可以看看代码加深理解:

public final boolean getAndSet(boolean newValue) {
    for (;;) {
        boolean current = get();
        if (compareAndSet(current, newValue))
            return current;
    }
}

getAndSet 中,如果布尔值在您 get() 旧值和您尝试更改其值之间发生了变化,compareAndSet 不会改变它的价值。因此,getAndSet 在循环中调用 compareAndSet,直到布尔值设置为新值。

关于您的代码示例:

flag.getAndSet(false) returns AtomicBoolean 的旧值。另一方面,flag.compareAndSet(x,false)(注意有两个参数)returnsAtomicBoolean 是否被修改,或者换句话说,returnsAtomicBoolean 的旧值是否为 x。

线程有点老,但没有人提到getAndSet 会比compareAndSet 更有效率。 CAS 是一个非常昂贵的指令(在所有 CPU 架构上,因此 JVM 在这里无关紧要)。所以它们并不完全等同。

所以关于 OP,这两种方法产生相同的行为,但不会有相同的性能,尽可能使用 getAndSet。