简体   繁体   English

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

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

Do I only need to mark a field volatile if multiple threads are reading it at the same time ? 如果多个线程同时读取它我是否只需要标记一个字段volatile?

What about the scenario where Thread A changes the value of a field, and Thread B evaluates it after Thread A is guaranteed to have completed? 那么线程A改变字段值的场景怎么样呢?线程B在保证线程A完成之后对它进行评估呢?

In my scenario, is there a happens-before relationship enforced (without the volatile keyword)? 在我的场景中,是否存在之前发生的关系(没有volatile关键字)?

You need the volatile keyword or some other synchronization mechanism to enforce the "happens before" relationship that guarantees visibility of the variable in threads other than the thread in which it was written. 您需要使用volatile关键字或其他一些同步机制来强制执行“之前发生”关系,以保证变量在除写入它之外的线程中的可见性。 Without such synchronization, everything is treated as happening "at the same time", even if it doesn't by wall clock time. 没有这样的同步,一切都被视为“同时”发生,即使它不是由挂钟时间。

In your particular example, one thing that may happen without synchronization is that the value written by thread A is never flushed from cache to main memory, and thread B executes on another processor and never sees the value written by thread A. 在您的特定示例中,没有同步可能发生的一件事是线程A写入的值永远不会从缓存刷新到主内存,线程B在另一个处理器上执行,永远不会看到线程A写入的值。

When you are dealing with threads, wall clock time means nothing. 当你处理线程时,挂钟时间没有任何意义。 You must synchronize properly if you want data to pass between threads properly. 如果希望数据在线程之间正确传递,则必须正确同步。 There's no shortcut to proper synchronization that won't cause you headaches later on. 没有正确同步的快捷方式,以后不会让您感到头痛。

In the case of your original question, some ways proper synchronization can be achieved are by using the volatile keyword, by using synchronized blocks, or by having the thread that is reading the value of the variable join() the thread in which the variable is written. 在您的原始问题的情况下,通过使用volatile关键字,使用synchronized块,或通过使用读取变量值的线程join()的变量为的线程,可以实现正确同步的某些方式。书面。

Edit: In response to your comment, a Future has internal synchronization such that calling get() on a Future establishes a "happens before" relationship when the call returns, so that also achieves proper synchronization. 编辑:响应您的注释, Future具有内部同步,以便在调用返回时调用Future上的get()建立“之前发生”关系,这样也可以实现正确的同步。

No, you don't need volatile ... 不,你不需要volatile ......

is there a happens-before relationship enforced (without the volatile keyword)? 是否有一个先发生过的关系强制执行(没有volatile关键字)?

...but your code needs to do something to establish "happens-before." ...但是你的代码需要做一些事情才能确定“先发生过”。

There will be a happens-before relationship if (and only if) your code does something that the "Java Language Specification" (JLS) says will establish "happens-before." 会有一个之前发生关系,如果(且当)你的代码做一些事情,在“Java语言规范”(JLS)说,将建立“之前发生。”

What about the scenario where Thread A changes the value of a field, and Thread B evaluates it after Thread A is guaranteed to have completed? 那么线程A改变字段值的场景怎么样呢?线程B在保证线程A完成之后对它进行评估呢?

Depends on what you mean by "guaranteed." 取决于你所说的“保证”。 If "guaranteed" means, "established happens-before," then your code will work as expected. 如果“保证”意味着“确定发生在之前”,那么您的代码将按预期工作。

One way you can guarantee it is for thread B to call threadA.join() . 一种方法可以保证它是线程B调用threadA.join() The JLS guarantees that if thread B calls threadA.join() , then everything thread A did must "happen before" the join() call returns. JLS保证如果线程B调用threadA.join() ,那么线程A所做的一切必须“在join()调用返回之前”发生。

You do not need any of the shared variables to be volatile if thread B only accesses them after joining thread A. 如果线程B在加入线程A之后只访问它们,则不需要任何共享变量是volatile

You can chose one of available options to achieve the same purpose. 您可以选择一个可用选项来实现相同的目的。

  1. You can use volatile to force all threads to get latest value of the variable from main memory. 您可以使用volatile来强制所有线程从主内存中获取变量的最新值。
  2. You can use synchronization to guard critical data 您可以使用synchronization来保护关键数据
  3. You can use Lock API 您可以使用Lock API
  4. You can use Atomic variables 您可以使用Atomic变量

Refer to this documentation page on high level concurrency constructs. 有关高级并发结构,请参阅此文档页面

Have a look at related SE questions: 看看相关的SE问题:

Avoid synchronized(this) in Java? 避免在Java中同步(this)?

What is the difference between atomic / volatile / synchronized? atomic / volatile / synchronized有什么区别?

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

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