Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 原子布尔中getAndSet和compareAndSet之间的差异_Java_Synchronization_Atomicity_Atomicboolean - Fatal编程技术网

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