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
Difference between getAndSet and compareAndSet in AtomicBoolean
提问by tmarwen
The thread title should be self-explnatory... I'm a bit confused between the specification of below methos from AtomicBoolean
class:
线程标题应该是不言自明的......我对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 if
condition:
我的看法是,当在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, compareAndSet
takes two arguments.
毫不奇怪,compareAndSet
需要两个参数。
In your specific case:
在您的具体情况下:
if (flag.getAndSet(false))
will setflag
tofalse
only if its previous value wastrue
- That would be the equivalent of
if (flag.compareAndSet(true, false))
if (flag.getAndSet(false))
将设置flag
于false
仅当它先前的值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, compareAndSet
won't change its value. Therefore, getAndSet
calls compareAndSet
in 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, compareAndSet
sets value only if the comparison pass while getAndSet
simply set the value and return the previous value.
同样在检查 javadoc 时,compareAndSet
仅当比较通过时才getAndSet
设置值,而只需设置值并返回前一个值。