易失性布尔值

发布于 2024-08-15 06:01:27 字数 183 浏览 10 评论 0原文

如果我有一个易失性布尔值(我们称其为有效),下面的代码在 Java 中是线程安全的吗?

if (valid)
  return;
valid = true;

或者,我是否需要同步,因为仅当 valid 为 false 时才将其设置为 true (因此 valid 集取决于其当前值)?

If I have a volatile boolean (let's call it valid), is the following piece of code thread-safe in Java?

if (valid)
  return;
valid = true;

Or, do I need to synchronize since valid is set to true only if it's false (hence set of valid depends on its current value)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(7

浮世清欢 2024-08-22 06:01:27

这需要同步,因为如果一个线程将 valid 评估为 false,然后在赋值之前暂停执行,然后另一个线程出现并检查 valid 为 false,在将 valid 设置为 true 之前,您将有两个线程运行以下代码从这里(这大概是你不想要的)。

This needs to be synchronized, because if one thread evaluates valid as false, and then suspends execution before the assignment, then another one comes along and also checks valid as false, before setting valid to true, you will have two threads running code following on from here (which presumably you don't want).

不知在何时 2024-08-22 06:01:27

使用原子布尔值。可以同时检查和设置实例。

Use AtomicBoolean. Instances can be simultaneously checked and set.

夏末 2024-08-22 06:01:27

它不是线程安全的。但如果这是整个代码,那就没关系了。

It isn't thread-safe. But if this is the whole code, it wouldn't matter.

定格我的天空 2024-08-22 06:01:27

编辑:一个全面的高级替代方案是AtomicBoolean,使用低级操作实现条件更新,无需同步。

对标志有两个单独的(即非原子)访问,因此同步是必要的,除非该线程是唯一对标志执行写操作的线程。即便如此,最好进行同步以确保将来发生变化。

Edit: An all-around superior alternative would be AtomicBoolean, which uses low-level operations to achieve conditional updates without synchronization.

There are two separate (i.e. non-atomic) accesses to the flag, thus synchronization is necessary unless this thread is the only one doing write operations on the flag. Even then it would probably be good to have synchronization just to be sure in case of future changes.

微凉 2024-08-22 06:01:27

您的代码不是线程安全的,但这实际上取决于您的其他代码是否安全。

您是否要求 valid = true 后面的代码只能由单个线程执行一次?如果是这样,那么您的代码就不安全,因为任意数量的线程都可以读取 validfalse 值,然后最终将其设置为 true >。例如:

if (valid)
  return;
// Imagine every single one of your threads stops and blocks here.
// They will all wake up again and set valid to true and then
// execute the code to follow.
valid = true;

但如果您只是想保证 valid = true 之后的代码最多由任何线程执行一次...那么您所拥有的就可以了。但如果这是您需要的行为,我会通过其他方式实现这一点,因为在这种情况下使用 易失性 看起来就像您不知道自己在做什么。例如,您可以不跨线程共享 valid 变量,并允许每个线程只执行一次代码。

另外,当在推理同步和易失性时有疑问......只需使用同步即可。它通常更清晰,并且会为您提供使用 易失性 所需的一切,除了更容易推理代码的工作原理之外。

Your code is not threadsafe, but it really depends on your other code whether or not it is safe to do that.

Do you require that the code following valid = true only be executed once by a single thread? If so, then your code is not safe because any number of threads can read a false value of valid, and then end up setting it to true. For example:

if (valid)
  return;
// Imagine every single one of your threads stops and blocks here.
// They will all wake up again and set valid to true and then
// execute the code to follow.
valid = true;

But if you just want to guarantee that the code after valid = true is executed at most one time by any thread... then what you have is fine. But if that's the behavior you require I would achieve that by other means, because using volatile in that case will just look like you don't know what you're doing. For example, you could just not share the valid variable across threads, and allow each thread to just execute the code once.

Also, when in doubt while reasoning about synchronization and volatile... just use synchronization. It is usually more clear, and will get you everything you wanted from using volatile, except it will be easier to reason how the code works.

樱花细雨 2024-08-22 06:01:27

线程安全是系统范围的属性。你不能孤立地看待一段代码并称其为线程安全/不安全。这取决于其他线程如何与其交互以及一致性要求是什么。话虽如此,大多数线程安全设计都有 while() 循环而不是 if() 块,因此,您的设计很可能是不正确的:)

thread-safety is a system wide property. you cannot look at a piece of code in isolation and call it thread safe/unsafe. it depends on how other threads interact with it and what is the consistency requirement. that being said, most thread-safe design has while() loop instead of if() block, so, your design is most likely incorrect:)

一抹苦笑 2024-08-22 06:01:27

根据 Brian Goetz 的精彩论文
https://www.ibm.com/developerworks/java/library/j- jtp06197/
“仅在有限的情况下,您可以使用易失性变量而不是锁。对于易失性变量,必须满足以下两个条件才能提供所需的线程安全性:

  • 对变量的写入不依赖于其当前值。
  • 变量 ”

基本上,这些条件表明可以写入易失性变量的有效值集独立于任何其他程序状态,包括变量的当前状态。
所以必须用锁来同步。它不是线程安全的。

According to great paper by Brian Goetz
https://www.ibm.com/developerworks/java/library/j-jtp06197/
"You can use volatile variables instead of locks only under a restricted set of circumstances. Both of the following criteria must be met for volatile variables to provide the desired thread-safety:

  • Writes to the variable do not depend on its current value.
  • The variable does not participate in invariants with other variables.

Basically, these conditions state that the set of valid values that can be written to a volatile variable is independent of any other program state, including the variable's current state."
So it must be synchronized with a lock. It is not thread-safe as is.

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