19

线程标题应该是不言自明的......我对AtomicBoolean类中以下方法的规范有点困惑:

  • java.util.concurrent.atomic.AtomicBoolean#compareAndSet
  • java.util.concurrent.atomic.AtomicBoolean#getAndSet

我的假设是,当在条件中用作布尔子句时,两者都会导致相同的行为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);
  }
}

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

如果我缺少内部差异,我将非常感谢有关如何以及何时使用其中的每一个的任何解释。

4

4 回答 4

24

文档很清楚。

  • getAndSet--> “以原子方式设置为给定值并返回前一个值。”
  • compareAndSet--> “如果当前值 == 预期值,则自动将值设置为给定的更新值。”

毫不奇怪,compareAndSet需要两个参数。

在您的具体情况下:

  • if (flag.getAndSet(false))仅当flagfalse先前的值是true
  • 那将相当于if (flag.compareAndSet(true, false))
于 2015-01-26T09:44:17.903 回答
9

您可以查看代码以更好地理解:

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

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

至于您的代码示例:

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

于 2015-01-26T09:47:12.970 回答
1

当我检查实现时,我发现以下

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

此外,在检查 javadoc 时,compareAndSet仅当比较通过时才设置值,而getAndSet只需设置值并返回前一个值。

于 2015-01-26T09:46:51.373 回答
0

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

因此,关于 OP,两种方法都会产生相同的行为,但性能不同,请尽可能使用 getAndSet。

于 2018-11-07T15:25:45.387 回答