易失性布尔值
如果我有一个易失性布尔值(我们称其为有效),下面的代码在 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这需要同步,因为如果一个线程将 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).
使用原子布尔值。可以同时检查和设置实例。
Use AtomicBoolean. Instances can be simultaneously checked and set.
它不是线程安全的。但如果这是整个代码,那就没关系了。
It isn't thread-safe. But if this is the whole code, it wouldn't matter.
编辑:一个全面的高级替代方案是
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.
您的代码不是线程安全的,但这实际上取决于您的其他代码是否安全。
您是否要求
valid = true
后面的代码只能由单个线程执行一次?如果是这样,那么您的代码就不安全,因为任意数量的线程都可以读取valid
的false
值,然后最终将其设置为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 afalse
value ofvalid
, and then end up setting it totrue
. For example: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 usingvolatile
in that case will just look like you don't know what you're doing. For example, you could just not share thevalid
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.线程安全是系统范围的属性。你不能孤立地看待一段代码并称其为线程安全/不安全。这取决于其他线程如何与其交互以及一致性要求是什么。话虽如此,大多数线程安全设计都有 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:)
根据 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:
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.