java AtomicBoolean 中 getAndSet 和 compareAndSet 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28147654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 13:04:52  来源:igfitidea点击:

Difference between getAndSet and compareAndSet in AtomicBoolean

javasynchronizationatomicityatomicboolean

提问by tmarwen

The thread title should be self-explnatory... I'm a bit confused between the specification of below methos from AtomicBooleanclass:

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

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

My assemption is that both would result in the same behavior when used as a boolean clause in an ifcondition:

我的看法是,当在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);
  }
}

Assuming that I want to retrieve the current flag value and update it automaticlly, shouldn't both methods produce the same behavior?

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

I would much appreciate any explanations regarding how and when to use each of those if I'm missing internal differences.

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

回答by Mena

The documentationis pretty clear.

文档是相当清楚的。

  • 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."
  • getAndSet--> “自动设置为给定值并返回前一个值。”
  • compareAndSet--> “如果当前值 == 预期值,则自动将值设置为给定的更新值。”

Not surprisingly, compareAndSettakes two arguments.

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

In your specific case:

在您的具体情况下:

  • if (flag.getAndSet(false))will set flagto falseonly if its previous value was true
  • That would be the equivalent of if (flag.compareAndSet(true, false))
  • if (flag.getAndSet(false))将设置flagfalse仅当它先前的值true
  • 那将相当于 if (flag.compareAndSet(true, false))

回答by Eran

You can look at the code for better understanding :

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

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

In getAndSet, if the value of the boolean has changed between the time you get()the old value and the time you try to change its value, compareAndSetwon't change its value. Therefore, getAndSetcalls compareAndSetin a loop until the boolean is set to the new value.

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

As to your code example :

至于你的代码示例:

flag.getAndSet(false)returns the old value of the AtomicBoolean. On the other hand, flag.compareAndSet(x,false)(note there are two arguments) returns whether the AtomicBoolean was modified, or in other words, it returns whether the old value of the AtomicBoolean was x.

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

回答by MappaM

The thread is a bit old but nobody mentioned that getAndSet will be more efficient than compareAndSet. CAS is a very costly instruction (on all CPU architectures, so JVM does not matter here). So they are not really equivalent.

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

So regarding the OP, both methods produce the same behaviour but it will not have the same performance, use getAndSet when you can.

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

回答by sodik

When I have checked the implementation I found following

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

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

Also when checking the javadoc, compareAndSetsets value only if the comparison pass while getAndSetsimply set the value and return the previous value.

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