2009-12-13 64 views
3

如果我有一个易变的布尔值(让我们把它称为有效的),下面的一段代码是Java中线程安全的吗?或者,我是否需要进行同步,因为只有当它为假时(因此设置的有效取决于其当前值),有效设置为真?)?volatile boolean

+1

易失性不会解决_race条件_易失性解决了存储在“有效”中的值与所有其他线程共享_访问valid_的问题,因此如果“有效”不是静态,并且没有静态引用包含“有效”的对象,那么没有其他线程会知道“有效” – Marco 2012-01-11 14:51:43

回答

4

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

+0

假设在有效=真实行之后有更多的代码 – Mete 2009-12-13 18:15:05

+0

然后同步 – Bozho 2009-12-13 18:25:08

+0

+1好回答:-) – dhiller 2009-12-13 20:37:59

8

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

+0

只有当实际上有两个线程执行相同的代码(或者正在执行写操作)时,才会出现这种情况 – 2009-12-13 18:31:07

+0

如果您的代码假定只有一个线程可以同时运行它,那么它不是'线程安全的'。如果你认为这个值不能被其他线程写入到可以访问这个变量的代码的一小部分中,那么这个问题必须适用于整个模块! – KernelJ 2009-12-13 18:43:52

+0

为了更明确一点,如果所有的线程只做读操作,一切都很好;如果其中只有一个能够写入该值,则在发生一致性问题的所有代码中都需要进行同步。 – KernelJ 2009-12-13 18:48:04

2

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

有两个单独的(即非原子)访问标志,因此同步是必要的除非这个线程是唯一一个在标志上执行写操作。即使这样,在未来发生变化的情况下进行同步也可能会很好。

5

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

+0

是的,很好的建议......但它首先需要你意识到你需要同步:-)。 – Tom 2009-12-13 18:39:09

1

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

您是否要求valid = true之后的代码只能由单个线程执行一次?如果是这样,那么你的代码是不安全的,因为任何数量的线程可以读取valid的值false,然后最终将其设置为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后的代码由任何线程最多一次执行...那么你有什么是好的。但如果这是你需要的行为,我会通过其他方式实现,因为在这种情况下使用volatile将看起来像你不知道你在做什么。例如,你可能不会在线程间共享变量valid,并允许每个线程只执行一次代码。

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

1

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

+1

通过使用原子或同步操作的线程安全性,而不是使用while循环。你说得对,线程安全是一个系统属性,但如果valid是一个共享变量,这个代码本质上不适合多线程。 – extraneon 2009-12-13 20:55:51

+0

我并不是说while循环使线程安全。我说线程安全代码通常有while循环,if-block通常表示错误。 – irreputable 2009-12-14 03:15:10

0

据布赖恩戈茨大纸 https://www.ibm.com/developerworks/java/library/j-jtp06197/ “您可以使用挥发性变量,而不是仅在有限的情况下锁定。为了提供期望的线程安全性,必须满足以下两个条件:

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

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