AtomicBoolean中getAndSet和compareAndSet之间的区别

时间:2015-01-26 09:40:30

标签: java synchronization atomicity atomicboolean

主题标题应该是自我探索的......我在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 个答案:

答案 0 :(得分:13)

documentation非常清楚。

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

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

在您的具体案例中:

  • if (flag.getAndSet(false))只有在flag的前一个值false
  • 时才会true设置为if (flag.compareAndSet(true, false))
  • 这相当于{{1}}

答案 1 :(得分:7)

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

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。

答案 2 :(得分:0)

当我检查了我在

后面找到的实现时
public final boolean getAndSet(boolean newValue) {
    for (;;) {
        boolean current = get();
        if (compareAndSet(current, newValue))
            return current;
    }
}

同样在检查javadoc时,compareAndSet仅在比较过程中设置值,getAndSet只需设置值并返回先前的值。

答案 3 :(得分:0)

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

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