什么时候最好在Java中使用volatile布尔值而不是AtomicBoolean?

我已经看过SO中的其他volatile和Atomicxxxx问题(包括这个 ),并且已经阅读了java.util.current.atomic的描述,对这些细微之处我还不太满意。

如果我试图决定使用volatile booleanAtomicBoolean ,是否有除AtomicBoolean提供的primefaces读取 – 修改 – 写入操作之间的实际差异? (比如compareAndSet()getAndSet()

假设我有

 volatile boolean flag; 

然后一个或多个线程设置标志(但不清除它)。 如果我有一个线程读取标志,如果设置,做一个动作,然后清除标志,是不是足够的?

AtomicBoolean的成本比volatile boolean更高

  • 内存空间
  • 性能命中( volatile boolean似乎需要内存屏蔽, AtomicBoolean似乎需要内存屏蔽+根据java.util.current.atomic描述对CAS操作进行一些次要locking)

我的直觉是和AtomicBoolean一起去,并且是安全的,但我想知道是否有使用volatile boolean的情况(例如,如果我有成千上万的实例,性能是一个问题)。

基本上所有的AtomicBoolean都是一个对象中的一个volatile boolean

每个对象会有一个小的开销。 可能微不足道,但可能更多的内存进入caching。

如果你需要使用AtomicBooleanFieldUpdater那么会有相当多的性能开销。如果你不打算经常这样做(如NIO所附)。

从实际的angular度来看, AtomicBooleanvolatile之间的主要区别在于,比较和设置操作不是primefaces的,而且是volatilevariables。

  volatile boolean b; void foo() { if( b ) { //Here another thread might have already changed the value of b to false b = false; } } 

但是看到所有的并发写入都是幂等的,而且只能从一个线程读取,这不应该是一个问题。

我不确定我是否完全同意这里的其他答案。 biziclop的答案是正确的,但我不确定我们可以断定你是安全的,除非我们知道更多的细节。

在简单的情况下,交错可能看起来像这样:

 Thread 1 (writer) Thread 2 (Writer) Thread 3 (Reader) ----------------- ----------------- ----------------- flag = true; if (flag) { flag = true; flag = false; doStuff(); 

这可能是好的(第二组flagtrue并不重要,因为doStuff()仍然可以看到任何线程2需要做的事情。

但是,如果你逆转线程3的顺序:

 Thread 1 (writer) Thread 2 (Writer) Thread 3 (Reader) ----------------- ----------------- ----------------- flag = true; if (flag) { doStuff(); flag = true; flag = false; 

那么线程2的更新可能会丢失。

当然,对于线程2所做的任何其他操作,您都必须同样小心,以确保线程3可见。如果线程2需要设置其他状态,则顺序也变得非常重要。

在简单的情况下,是的,你很好,但如果它变得比简单的标志轻弹更复杂,那么这变得更难以推理。

这里有很多很好的信息。 但是,我会添加另一个可能有用的区别。 你可以有一个AtomicBooleans数组,但你不能(据我所知)有一个可变的布尔值数组。

然后一个或多个线程设置标志(但不清除它)。 如果我有一个线程读取标志,如果设置,做一个动作,然后清除标志,是不是足够的?

是的,如果你不需要AtomicBoolean的特殊function,那么使用volatile就可以了。 事实上,这是挥发性的less数合理用途之一。