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

时间:2016-06-05 20:18:04

标签: java multithreading volatile

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

线程A更改字段值的情况如何,线程B在保证线程A完成后对其进行评估?

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

3 个答案:

答案 0 :(得分:5)

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

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

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

对于原始问题,可以通过使用volatile关键字,使用synchronized块或通过使用正在读取值的线程来实现正确同步的一些方法。变量join()写入变量的线程。

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

答案 1 :(得分:0)

不,你不需要volatile ...

  

是否有强制执行的关系(没有volatile关键字)?

...但是你的代码需要某些东西来建立"之前发生的事情。"

发生在之前的关系如果(并且 if)你的代码做了什么" Java语言规范" (JLS)表示将建立"之前发生。"

  

线程A更改字段值的情况如何,线程B在保证线程A完成后对其进行评估?

取决于您的意思"保证。"如果"保证"意味着,"建立发生在之前,"然后你的代码将按预期工作。

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

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

答案 2 :(得分:0)

您可以选择其中一个可用选项来达到同样的目的。

  1. 您可以使用volatile强制所有线程从主内存中获取变量的最新值。
  2. 您可以使用synchronization来保护关键数据
  3. 您可以使用Lock API
  4. 您可以使用Atomic变量
  5. 有关高级并发构造的信息,请参阅此文档page

    查看相关的SE问题:

    Avoid synchronized(this) in Java?

    What is the difference between atomic / volatile / synchronized?