Java 需要同步布尔成员变量的设置吗?
嘿,我正在处理我继承的一些代码,看起来一个线程正在设置一个布尔成员变量,而另一个线程在while循环中检查它。这真的可以工作吗?或者我应该将其更改为在布尔变量上使用同步getter或setter吗?几乎可以肯定,您将需要在更高级别上添加锁定。仅仅在字段的单个访问周围添加Java 需要同步布尔成员变量的设置吗?,java,multithreading,Java,Multithreading,嘿,我正在处理我继承的一些代码,看起来一个线程正在设置一个布尔成员变量,而另一个线程在while循环中检查它。这真的可以工作吗?或者我应该将其更改为在布尔变量上使用同步getter或setter吗?几乎可以肯定,您将需要在更高级别上添加锁定。仅仅在字段的单个访问周围添加synchronized,很少有帮助。如果组件操作是独立的线程安全的,那么复合操作将不是线程安全的 作为一个例子,考虑删除线程安全文档的内容。该文档提供了两个相关的线程安全操作:删除两个索引之间的内容和一个长度操作。所以你得到了长
synchronized
,很少有帮助。如果组件操作是独立的线程安全的,那么复合操作将不是线程安全的
作为一个例子,考虑删除线程安全文档的内容。该文档提供了两个相关的线程安全操作:删除两个索引之间的内容和一个长度操作。所以你得到了长度,然后从零删除到长度,对吗?在读取长度和删除内容之间,文档可能会改变长度,这是一种竞争。在给定操作的情况下,无法使操作线程安全。(示例取自Swing Text。)
我建议将布尔值声明为volatile,并同步读写访问如果读写一个像bool或int这样声明为volatile的原语,那就足够了。当一个线程读取时,另一个线程将完成写入。变量永远不会处于无效状态 可以公平地说,总的来说,volatile关键字 Java缺乏文档,理解能力差,很少使用。使 更糟糕的是,从Java5开始,它的正式定义实际上发生了变化。 本质上,volatile用于指示变量的值将 可以被不同的线程修改 声明易失性Java变量意味着:如果使用Java1.5+,则应使用同步原语
如果您遵循链接,它有一个很好的示例说明如何使用它。如果它是纯布尔值,则不能保证工作,因为java的内存模型,其中一个线程可能看不到更新的布尔值,您可以
- 创建一个同步的getter/setter 或
- 将布尔值声明为volatile,是理解volatile的好资源
while(foo.myVolatileBoolean) {
...
}
线程2:
foo.myVolatileBoolean = false; //thread 1 might never catch thisone.
...
foo.myVolatileBoolean = true;
如果这是一个问题,你需要监视布尔值的变化,考虑使用WaIT()/NOTIFY()或
这听起来很混乱。(另外,volatile
是出人意料的无益(在低级别时除外),因为操作通常需要多个组件操作。)@tackline你的意思是因为它是皮带和支架方法而混淆吗?如果是这样,那么尽管我理解Java编程模型可能表明volatile本身就足够了,但对于我可能遇到的所有JVM实现,尤其是在多核环境中运行时,我仍然怀疑这种说法。在任何情况下,即使我的偏执狂没有被宣布,volatile本身通常都不是一个足够强烈的提示,提示维护人员,关于所讨论的布尔值,他们需要注意一些重要的事情。您应该声明一个变量volatile
,或者使用synchronized
访问器。两者兼而有之只会降低性能并增加复杂性。Tom是对的,volatile的正确用法大部分是由java.concurrent gurus保留的。到目前为止,答案不错,伙计们,我想while循环可能正在缓存它试图在本地检查的变量。我现在添加volatile并将变量放入同步getter和setter中。我认为您没有正确阅读答案(和文档),尤其是Tom Hawtin的答案。同步访问volatile变量是一个矛盾的说法。我同意volatile将保护您的布尔变量,并确保它被正确更新和读取,但您需要从全局出发,确保对象始终处于一致状态。volatile
在JLS和JVM规范中有明确规定。但是,它的使用频率似乎远远超过了人们对其后果的理解。@Tom Hawtin-我们需要了解它的局限性。在有限的情况下,它是一个强大的工具。虽然您所说的布尔(在某些情况下是int)原语是正确的,但在执行int++之类的操作时要小心使用int。虽然这看起来是一个单独的操作,但实际上并不是,在这种情况下仅仅使用volatile是不够的。@Jeff Storey int++实际上是读取变量、递增和写入,因此,+=N.B.这个答案似乎很大程度上是从我的网页上剽窃的:+1这是一个很好的观点,可以添加一些透视图来观察不仅仅是布尔变量。你的观点很好,但根据所问的问题,没有上下文来引入复合参数。这个问题是关于布尔型读写器的问题。Showboating?@bjg线程涉及上下文。它本质上是非本地的。我相信这个问题很可能不止一个布尔值。当然,对于这个领域的新手来说,用复杂的代码解决一个特例问题是毫无帮助的。