访问/写入布尔对象是否需要同步

时间:2010-04-16 03:49:33

标签: java synchronization boolean

这似乎是一个非常愚蠢的问题。 考虑一下:

我有一个带有getter和setter的简单Boolean对象。现在,很多线程都经常调用这两种方法。

  1. 我是否需要为此布尔值进行同步?
  2. 还有布尔分配原子操作吗?
  3. [UPDATE]:  我已经知道Atomic布尔了。我已经有了很多不同的解决方案,但我是专门为上述2个问题寻找答案和答案的理由。

7 个答案:

答案 0 :(得分:10)

不,布尔访问不是原子的(在机器代码级别上),尽管它确实需要“在Java中只进行一次操作”。

因此,是的,你需要同步布尔值。

请参阅this presentation的幻灯片4-6以获取代码示例。

在相关说明中,you should not synchronize on a Boolean

答案 1 :(得分:3)

  1. 是。但是,如果它是仅从一个线程编写的标志,并且您希望确保所有线程的可见性,那么便宜的替代方案是使用volatile

  2. 是 - 即使对象的内部表示(即boolean包装器中的实际Boolean标志)是64位,因此可能在并发情况下“分裂” ,布尔值只能有两个值中的一个,对吧?所以普通的赋值(get 集)是原子的,但是如果你正在做其他事情(比如check-then-act),例如x = !x,那么除非同步,否则它当然不是原子的。

答案 2 :(得分:3)

  1. 从技术角度来看,在另一个线程中感知一个线程中的写入不需要同步。你需要的是发生在边缘之前。可能会使用volatilesynchronized来实现之前发生的边缘。这两种技术都会产生同步边缘。因此,在实践中,您可能会使用同步来管理布尔值的状态。
  2. 是。请注意,您没有更改Boolean对象的状态。您只是修改对Boolean对象的引用。语言规范的第17.7节规定“写入和读取引用始终是原子的。”
  3. 更新:让我解释一下前发生边缘的必要性。如果没有先发生边缘,那么一个线程对变量所做的更改就不能保证被其他线程所感知。不仅可以在诸如读取和写入之间的不良时间感知改变。这种变化可能从未被感知。

    假设我们有一个布尔变量,我们将其初始化为false。然后我们开始两个线程。第一个线程将变量设置为true并停止。第二个线程不断检查变量,直到它为真,然后停止。无法保证第二个线程会将变量视为真。

答案 3 :(得分:2)

使用AtomicBoolean

答案 4 :(得分:1)

  1. 不,你没有。但是声明变量volatile,以便这些值反映在访问布尔值的所有线程中。如果您查看AtomicBoolean的{​​{1}}方法,它也没有任何同步。

  2. 是的,实际上分配是原子的。只是设置值不需要同步。但是,如果你想做类似的事情:

    set(..)

    然后你需要同步(或if (!bool) { bool = false; } ,这比同步更有效)

答案 5 :(得分:1)

http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html 说原始变量的读写是原子的。

因此可以强制执行严格的交替,或者在使用布尔值的关系之后执行(或者在缓存效果的情况下使用volatile布尔值)

答案 6 :(得分:0)

即使它是原子的,仍然存在同步问题,因为您可能会在某个时间检查该值 例如 if(boolVar == true) - >其他线程控制do_something();