线程标题应该是自我解释的...我对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);
}
}
假设我想检索当前标志值并自动更新它,这两种方法不应该产生相同的行为吗?
如果我缺少内部差异,我将非常感谢有关如何以及何时使用其中每个的解释。
文档非常清楚。
-
getAndSet
-->"原子方式设置为给定值并返回前一个值。 -
compareAndSet
-->"如果当前值 == 预期值,则以原子方式将值设置为给定的更新值。
毫不奇怪,compareAndSet
有两个论点。
在您的具体情况中:
-
if (flag.getAndSet(false))
将flag
设置为仅当其先前的值为false
时true
- 这相当于
if (flag.compareAndSet(true, false))
您可以查看代码以更好地理解:
public final boolean getAndSet(boolean newValue) {
for (;;) {
boolean current = get();
if (compareAndSet(current, newValue))
return current;
}
}
在getAndSet
中,如果布尔值的值在您get()
旧值和您尝试更改其值之间发生了变化,则compareAndSet
不会更改其值。因此,getAndSet
调用compareAndSet
循环,直到布尔值设置为新值。
至于你的代码示例:
flag.getAndSet(false)
返回原子布尔值的旧值。另一方面,flag.compareAndSet(x,false)
(注意有两个参数)返回 AtomicBoolean 是否被修改,或者换句话说,它返回 AtomicBoolean 的旧值是否为 x。
当我检查了以下实现时,我发现以下内容
public final boolean getAndSet(boolean newValue) {
for (;;) {
boolean current = get();
if (compareAndSet(current, newValue))
return current;
}
}
同样在检查javadoc时,compareAndSet
仅在比较通过时才设置值,而getAndSet
只是设置值并返回前一个值。
线程有点旧,但没有人提到getAndSet会比compareAndSet更有效。CAS 是一个非常昂贵的指令(在所有 CPU 架构上,所以 JVM 在这里无关紧要)。所以它们并不是真正等同的。
因此,关于OP,两种方法都会产生相同的行为,但它不会具有相同的性能,请尽可能使用getAndSet。