访问/写入布尔对象是否需要同步
这可能看起来是一个非常愚蠢的问题。 考虑一下:
我有一个带有 getter 和 setter 的简单布尔对象。现在这两个方法都会被很多线程频繁调用。
- 我需要同步这个布尔值吗?
- 布尔赋值也是原子操作吗?
[更新]: 我已经了解原子布尔了。我已经有很多不同的解决方案,但我专门寻找上述两个问题的答案和答案的理由。
This may seem a very silly question.
Consider this:
I have a simple Boolean object with a getter and a setter. Now both of the methods are called from a lot of threads very frequently.
- Do I need to have a synchronization for this boolean?
- Also are Boolean assignments atomic operations?
[UPDATE]:
I know about Atomic Boolean already. I already have a lot of varied solutions, But I was specifically looking for answers and justification of answers for the above 2 question.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
不,布尔访问不是原子的(在机器代码级别),尽管它确实“在 Java 中只需要 1 次操作”。
因此,是的,您确实需要布尔同步。
有关代码示例,请参阅本演示文稿的幻灯片 4-6。
在相关说明中,您不应在布尔值上同步
No, Boolean access is NOT atomic (on the level of machine code), although it does take "only 1 operation in Java".
Therefore, yes, you do need synchronization for Boolean.
Please see slides 4-6 of this presentation for code examples.
On a related note, you should not synchronize on a Boolean
是的。但是,如果它是仅从一个线程写入的标志,并且您希望确保对所有线程的可见性,那么一种廉价的替代方案是使用
易失性
。是的 - 即使对象的内部表示(即
Boolean
包装器内的实际boolean
标志)是 64 位,因此它可能会被“分割”在并发情况下,布尔值只能有两个值之一,对吧?因此,简单的分配(获取或设置)是原子的,但如果您正在执行其他操作(例如检查然后执行),例如x = ! x
,那么除非同步,否则它当然不是原子的。Yes. But if it's a flag that is written from one thread only and you want to ensure visibility to all threads, then a cheap alternative is using
volatile
.Yes - even though the internal representation of the object (i.e. the actual
boolean
flag inside theBoolean
wrapper) were 64 bit and it could therefore get "split" in a concurrent situation, a boolean can only have one of the two values, right? So plain assignments (get or set) are atomic, but if you're doing anything else (like check-then-act), for instancex = !x
, then it's of course not atomic unless synchronized.易失性
或同步
来实现发生在边缘之前。这两种技术都会产生同步边缘。因此,在实践中,您可能会使用同步来管理布尔值的状态。更新:让我阐述一下对发生在边缘之前的需求。如果没有“happens-before”边缘,则无法保证一个线程对变量所做的更改能够被其他线程感知到。这不仅仅是在不恰当的时间(例如在读和写之间)感知到变化。这种变化可能永远被察觉。
假设我们有一个布尔变量,我们将其初始化为 false。然后我们启动两个线程。第一个线程将变量设置为 true 并停止。第二个线程不断检查变量,直到它为真,然后停止。无法保证第二个线程会将该变量视为 true。
volatile
orsynchronized
will be used to achieve the happens-before edge. Both of those techniques result in a synchronized-with edge. So, in practice, you will probably use synchronization to manage the state of your boolean.Update: Let me expound upon the need for a happens-before edge. Without a happens-before edge, then the changes that one thread makes to the variable are not guaranteed to ever be perceived by the other threads. It is not simply that the change may be perceived at a bad time such as in between a read and a write. The change may never be perceived.
Let's say that we have a boolean variable that we initialize to false. Then we start two threads. The first thread sets the variable to true and stop. The second thread continually checks the variable until it is true, after which it stops. There is no guarantee that the second thread will ever see the variable as true.
使用 AtomicBoolean 。
Use AtomicBoolean.
不,你不知道。但声明变量
易失性
,以便这些值反映在访问该布尔值的所有线程中。如果您查看AtomicBoolean
的set(..)
方法,您会发现它也没有任何同步。是的,实际上赋值是原子的。只需设置该值即可,无需同步。但是,如果您想做类似的事情:
那么你需要同步(或者
AtomicBoolean
,它比同步更有效)No, you don't. But declare the variable
volatile
so that the values are reflected in all threads that are accessing the boolean. If you look atAtomicBoolean
'sset(..)
method, it doesn't have any synchronization either.Yes, practically assignment is atomic. Just setting the value does not need synchronization. However, if you want to do something like:
then you need synchronization (or
AtomicBoolean
, which is more efficient than synchronization)http://docs.oracle.com/javase/tutorial/essential/concurrency /atomic.html
说原始变量的读写是原子的。
因此,可以强制执行严格的交替,或者在使用布尔值(或在缓存效果的情况下使用易失性布尔值)的关系之后发生
http://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
says that read and write of primitive variables is atomic.
Hence it is possible to enforce strict alternation or happens after relationships using boolean (or volatile boolean in case of cache effects)
即使它是原子的,仍然存在同步问题,因为您有时会检查该值
例如
如果(布尔变量==true)
->其他线程控制
do_something();
even if it was atomic there are still syncronization isues since you will propably check the value sometime
e.g.
if (boolVar==true)
-> other thread takes control
do_something();