volatile布尔值

时间:2009-12-13 18:10:23

标签: java synchronization volatile

如果我有一个volatile布尔值(让它调用它有效),下面的代码片段是否在Java中是线程安全的?

if (valid)
  return;
valid = true;

或者,我是否需要同步,因为只有在有效时才设置为true(因此有效集取决于其当前值)?

7 个答案:

答案 0 :(得分:8)

这需要同步,因为如果一个线程将valid计算为false,然后在赋值之前暂停执行,那么另一个线程出现并且也检查有效为false,在将valid设置为true之前,将运行两个线程从这里开始的代码(可能是你不想要的)。

答案 1 :(得分:5)

使用AtomicBoolean。可以同时检查和设置实例。

答案 2 :(得分:4)

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

答案 3 :(得分:2)

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

对标志有两个独立的(即非原子)访问,因此同步是必要的,除非这个线程是唯一一个对标志进行写操作的线程。即便如此,为了确保未来的变化,同步也可能是件好事。

答案 4 :(得分:1)

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

您是否要求valid = true之后的代码只能由一个线程执行一次?如果是这样,那么您的代码就不安全,因为任意数量的线程都可以读取false valid的值,然后最终将其设置为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;

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

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

答案 5 :(得分:1)

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

答案 6 :(得分:0)

Brian Goetz的伟大论文 https://www.ibm.com/developerworks/java/library/j-jtp06197/ “只有在一组有限的情况下才能使用volatile变量而不是锁。对于volatile变量,必须满足以下两个条件才能提供所需的线程安全性:

  • 写入变量不依赖于其当前值。
  • 该变量不参与其他变量的不变量。

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