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

时间:2011-02-02 15:15:20

标签: java concurrency atomic volatile

我已经在SO中查看了其他volatile和Atomicxxxx问题(包括this one)并阅读了the description of java.util.current.atomic,我对细微差别不太满意。

如果我在尝试使用volatile booleanAtomicBoolean之间做出决定,除了AtomicBoolean提供的原子读取 - 修改 - 写入操作之外,是否存在实际差异? (例如compareAndSet()getAndSet()

假设我有

volatile boolean flag;

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

而言,AtomicBoolean的成本是否高于volatile布尔值
  • 记忆空间
  • 性能命中(volatile boolean似乎需要内存防护,AtomicBoolean似乎需要内存防护+根据java.util.current.atomic说明对CAS操作进行一些小锁定)

我的直觉调用是使用AtomicBoolean并且是安全的,但我想了解是否有使用volatile boolean的情况(例如,如果我有数千个实例并且性能是一个问题)

5 个答案:

答案 0 :(得分:70)

从实际角度来看,AtomicBooleanvolatile之间的主要区别在于比较和设置操作与volatile变量不是原子操作。

 volatile boolean b;

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

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

答案 1 :(得分:19)

我不确定我是否完全赞同其他答案; 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需要设置其他状态,那么命令也很重要。

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

答案 2 :(得分:17)

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

每个对象的开销很小。可能无关紧要,但可能有更多内存进入缓存。

如果你需要使用AtomicBooleanFieldUpdater,那么会有很多性能开销。如果你不经常这样做(如NIO中的attach),那就没关系。

答案 3 :(得分:7)

这里有很多好消息。但是,我会添加另一个可能有用的差异。你可以有一个AtomicBooleans数组,但你不能(据我所知)有一系列挥发性布尔值。

答案 4 :(得分:2)

  

然后一个或多个线程设置标志   (但不清楚)。如果我有一个   读取标志的线程,如果   设置,执行操作,然后清除   国旗,是否充足?

是的,如果你不需要AtomicBoolean的特殊能力,那么使用volatile就可以了。实际上,这是volatile的少数合理用途之一。