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

发布于 2024-08-28 17:32:38 字数 226 浏览 5 评论 0原文

这可能看起来是一个非常愚蠢的问题。 考虑一下:

我有一个带有 getter 和 setter 的简单布尔对象。现在这两个方法都会被很多线程频繁调用。

  1. 我需要同步这个布尔值吗?
  2. 布尔赋值也是原子操作吗?

[更新]: 我已经了解原子布尔了。我已经有很多不同的解决方案,但我专门寻找上述两个问题的答案和答案的理由。

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.

  1. Do I need to have a synchronization for this boolean?
  2. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

陌路终见情 2024-09-04 17:32:38

不,布尔访问不是原子的(在机器代码级别),尽管它确实“在 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

梦言归人 2024-09-04 17:32:38
  1. 是的。但是,如果它是仅从一个线程写入的标志,并且您希望确保对所有线程的可见性,那么一种廉价的替代方案是使用 易失性

  2. 是的 - 即使对象的内部表示(即 Boolean 包装器内的实际 boolean 标志)是 64 位,因此它可能会被“分割”在并发情况下,布尔值只能有两个值之一,对吧?因此,简单的分配(获取设置)是原子的,但如果您正在执行其他操作(例如检查然后执行),例如x = ! x,那么除非同步,否则它当然不是原子的。

  1. 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.

  2. Yes - even though the internal representation of the object (i.e. the actual boolean flag inside the Boolean 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 instance x = !x, then it's of course not atomic unless synchronized.

不念旧人 2024-09-04 17:32:38
  1. 从技术角度来看,一个线程中的写入不需要同步即可在另一个线程中感知。您需要的是一个发生在边缘。很可能使用易失性同步来实现发生在边缘之前。这两种技术都会产生同步边缘。因此,在实践中,您可能会使用同步来管理布尔值的状态。
  2. 是的。请注意,您没有更改布尔对象的状态。您仅修改对布尔对象的引用。语言规范第 17.7 节指出“引用的写入和读取始终是原子的”。

更新:让我阐述一下对发生在边缘之前的需求。如果没有“happens-before”边缘,则无法保证一个线程对变量所做的更改能够被其他线程感知到。这不仅仅是在不恰当的时间(例如在读和写之间)感知到变化。这种变化可能永远被察觉。

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

  1. From a technical perspective, synchronization is not required for writes in one thread to be perceived in another thread. What you do need is a happens-before edge. It is likely that either volatile or synchronized 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.
  2. Yes. Note that you are not changing the state of the Boolean object. You are only modifying the reference to the Boolean object. Section 17.7 of the language specification states that "writes to and reads of references are always atomic."

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.

十六岁半 2024-09-04 17:32:38
  1. 不,你不知道。但声明变量易失性,以便这些值反映在访问该布尔值的所有线程中。如果您查看 AtomicBooleanset(..) 方法,您会发现它也没有任何同步。

  2. 是的,实际上赋值是原子的。只需设置该值即可,无需同步。但是,如果您想做类似的事情:

    if (!bool) {
       布尔=假;
    }
    

    那么你需要同步(或者AtomicBoolean,它比同步更有效)

  1. 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 at AtomicBoolean's set(..) method, it doesn't have any synchronization either.

  2. Yes, practically assignment is atomic. Just setting the value does not need synchronization. However, if you want to do something like:

    if (!bool) {
       bool = false;
    }
    

    then you need synchronization (or AtomicBoolean, which is more efficient than synchronization)

与酒说心事 2024-09-04 17:32:38

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)

笑,眼淚并存 2024-09-04 17:32:38

即使它是原子的,仍然存在同步问题,因为您有时会检查该值
例如
如果(布尔变量==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();

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文