繁体   English   中英

我需要volatile关键字吗? (JAVA)

[英]Do I need the volatile keyword? (Java)

如果多个线程同时读取它我是否只需要标记一个字段volatile?

那么线程A改变字段值的场景怎么样呢?线程B在保证线程A完成之后对它进行评估呢?

在我的场景中,是否存在之前发生的关系(没有volatile关键字)?

您需要使用volatile关键字或其他一些同步机制来强制执行“之前发生”关系,以保证变量在除写入它之外的线程中的可见性。 没有这样的同步,一切都被视为“同时”发生,即使它不是由挂钟时间。

在您的特定示例中,没有同步可能发生的一件事是线程A写入的值永远不会从缓存刷新到主内存,线程B在另一个处理器上执行,永远不会看到线程A写入的值。

当你处理线程时,挂钟时间没有任何意义。 如果希望数据在线程之间正确传递,则必须正确同步。 没有正确同步的快捷方式,以后不会让您感到头痛。

在您的原始问题的情况下,通过使用volatile关键字,使用synchronized块,或通过使用读取变量值的线程join()的变量为的线程,可以实现正确同步的某些方式。书面。

编辑:响应您的注释, Future具有内部同步,以便在调用返回时调用Future上的get()建立“之前发生”关系,这样也可以实现正确的同步。

不,你不需要volatile ......

是否有一个先发生过的关系强制执行(没有volatile关键字)?

...但是你的代码需要做一些事情才能确定“先发生过”。

会有一个之前发生关系,如果(且当)你的代码做一些事情,在“Java语言规范”(JLS)说,将建立“之前发生。”

那么线程A改变字段值的场景怎么样呢?线程B在保证线程A完成之后对它进行评估呢?

取决于你所说的“保证”。 如果“保证”意味着“确定发生在之前”,那么您的代码将按预期工作。

一种方法可以保证它是线程B调用threadA.join() JLS保证如果线程B调用threadA.join() ,那么线程A所做的一切必须“在join()调用返回之前”发生。

如果线程B在加入线程A之后只访问它们,则不需要任何共享变量是volatile

您可以选择一个可用选项来实现相同的目的。

  1. 您可以使用volatile来强制所有线程从主内存中获取变量的最新值。
  2. 您可以使用synchronization来保护关键数据
  3. 您可以使用Lock API
  4. 您可以使用Atomic变量

有关高级并发结构,请参阅此文档页面

看看相关的SE问题:

避免在Java中同步(this)?

atomic / volatile / synchronized有什么区别?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM