Java 原子布尔中getAndSet和compareAndSet之间的差异
线程标题应该是自解释的。。。我对Java 原子布尔中getAndSet和compareAndSet之间的差异,java,synchronization,atomicity,atomicboolean,Java,Synchronization,Atomicity,Atomicboolean,线程标题应该是自解释的。。。我对AtomicBoolean类中的以下方法的规范感到有点困惑: java.util.concurrent.AtomicBoolean#compareAndSet java.util.concurrent.AtomicBoolean#getAndSet 我的断言是,当在if条件中用作布尔子句时,两者将导致相同的行为: 公共类测试{ 私有AtomicBoolean标志=AtomicBoolean(false); public void processSomeActi
AtomicBoolean
类中的以下方法的规范感到有点困惑:
java.util.concurrent.AtomicBoolean#compareAndSet
java.util.concurrent.AtomicBoolean#getAndSet
if
条件中用作布尔子句时,两者将导致相同的行为:
公共类测试{
私有AtomicBoolean标志=AtomicBoolean(false);
public void processSomeAction(){
if(flag.getAndSet(false)){//这不应该与flag.compareAndSet(false)类似吗
//处理一些行动
}
}
//...
私有void internalMutatorMethod(){
//然后,是否有一些工作人员更新原子标志
flas.set(真);
}
}
假设我想要检索当前标志值并自动更新它,这两种方法不应该产生相同的行为吗
如果我遗漏了内部差异,我将非常感谢任何关于如何以及何时使用这些差异的解释。问题非常清楚
-->“自动设置为给定值并返回上一个值。”getAndSet
-->“如果当前值==预期值,则自动将该值设置为给定的更新值。”compareAndSet
compareAndSet
接受两个参数
在您的具体情况下:
仅当其先前的值为if(flag.getAndSet(false))
true时才会将
标志设置为
false
- 这相当于
if(flag.compareAndSet(true,false))
public final boolean getAndSet(boolean newValue) {
for (;;) {
boolean current = get();
if (compareAndSet(current, newValue))
return current;
}
}
另外,在检查javadoc时,
compareAndSet
仅在比较通过时设置值,而getAndSet
只需设置值并返回以前的值。您可以查看代码以更好地理解:
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 线程有点旧,但是没有人提到getAndSet比compareAndSet更有效。
CAS是一个非常昂贵的指令(在所有CPU架构上,所以JVM在这里并不重要)。因此,它们实际上并不等同
因此,关于OP,两种方法都会产生相同的行为,但不会有相同的性能,请尽可能使用getAndSet。compareAndSet有两个参数。javadoc表明它与getAndSet完全不同您可以为compareAndSet编写一个调用,该调用的功能与getAndSet相同,但这几乎不值得一提。是的,文档非常清晰,正如您所建议的那样,我可以从总体上看出区别。。。但我想看看我在主线程中编写的代码片段的不同之处。这有什么不同吗?这正是我期待确认的。。。在我的例子中,它们应该是等价的:)@tmarwen您错误地假设compareAndSet只接受一个参数。“if(flag.getAndSet(false))将仅在其先前的值为true时将flag设置为false”-这是不正确的。getAndSet()总是将该值设置为前一个值是true还是false。这仅在早期版本的JDK中才是true。jdk8将其重写为do-while循环,jdk9到jdk14使用
VarHandle
实现,即native
。