简体   繁体   English

Java中synchronized/volatile的变量可见性影响程度是多少

[英]What is the extent of variable visibility effect of synchronized/volatile in Java

According to "Java Concurrency in Practice":根据“Java并发实践”:

everything A did in or prior to a synchronized block is visible to B when it executes a synchronized block guarded by the same lockA 在同步块中或同步块之前执行的所有操作对 B 执行由同一锁保护的同步块时,它都是可见的

and

The visibility effects of volatile variables extend beyond the value of the volatile variable itself. volatile 变量的可见性影响超出了 volatile 变量本身的值。 When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable当线程 A 写入一个 volatile 变量,随后线程 B 读取同一个变量时,在写入 volatile 变量之前对 A 可见的所有变量的值在读取 volatile 变量后对 B 可见

what I'm not clear about is what dose it mean by everything and all variables ?我不清楚的是一切所有变量的含义是什么? Dose it mean everything literally?它的字面意思是一切吗? If we have a class like this:如果我们有一个这样的类:

class MyClassA{
  int a;
  int[] array = new int[10];
  MyClassB myClass; // a class with similar properties

  void notSyncronizedMethod(){
      // do something with a, array[3], myClass.a, myClass.array[3]
  }
  syncronized void syncronizedMethodA(){
      // update value of a, array[3], myClass.a, myClass.array[3]
  }
  syncronized void syncronizedMethodB(){
      // do something with a, array[3], myClass.a, myClass.array[3]
  }
}

if we call syncronizedMethodA() in one thread and then call syncronizedMethodB() or notSyncronizedMethod() in another thread, assume the time order is stritly garanteed, will call of syncronizedMethodB() and notSyncronizedMethod() use the latest variable value set by syncronizedMethodA() .如果我们调用syncronizedMethodA()在一个线程,然后调用syncronizedMethodB()notSyncronizedMethod()在另一个线程,假设时间顺序stritly保证下,将调用syncronizedMethodB()notSyncronizedMethod()通过使用最新的变量值设定syncronizedMethodA() I'm sure value of a is OK for syncronizedMethodB() , but what about elements of reference types like array[3], myClass.a or even myClass.myClass.array[3]?我确定 a 的值对于syncronizedMethodB()是可以的,但是对于像 array[3]、myClass.a 甚至 myClass.myClass.array[3] 这样的引用类型的元素呢? What about notSyncronizedMethod() with value updated by an syncronized method?值由同步方法更新的notSyncronizedMethod()怎么样?

In order to figure out what visibility guarantees are provided, you need to understand the Java Memory Model a little better, and more specifically, what happens-before means in the context of the JMM.为了弄清楚提供了哪些可见性保证,您需要更好地理解 Java 内存模型,更具体地说,在 JMM 的上下文中,先发生什么意味着什么。 The JMM describes things that happen as actions , for example, normal reads and writes, volatile reads and writes, lock, unlock, etc. JMM 将发生的事情描述为动作,例如,正常读取和写入、易失性读取和写入、锁定、解锁等。

There are a handful of rules in the JMM that establish when one action happens-before another action. JMM 中有一些规则可以确定一个动作何时发生 - 在另一个动作之前。 The rules relevant in your case are the following:与您的情况相关的规则如下:

The single thread rule : in a given thread, action A happens-before action B if A precedes B in program order.单线程规则:在给定的线程中,如果 A 在程序顺序中先于 B,则动作 A 发生在动作 B 之前。

The monitor lock rule (synchronized): An unlock of given monitor happens-before a subsequent lock on the same monitor.监视器锁定规则(同步):给定监视器的解锁发生在同一监视器上的后续锁定之前。

It's important to know that happens-before is transitive, ie if hb(a, b) and hb(b, c), then hb(a, c).重要的是要知道happens-before是可传递的,即如果hb(a, b) 和hb(b, c),那么hb(a, c)。

In your example, one thread releases the monitor when exiting syncronizedMethodA() , and another thread subsequently acquires the monitor when entering syncronizedMethodB() .在您的示例中,一个线程在退出syncronizedMethodA()时释放监视器,而另一个线程随后在进入syncronizedMethodB()时获取监视器。 That's one happens-before relation.这是一个发生在之前的关系。 And since HB is transitive, actions performed in syncronizedMethodA() become visible for any thread that subsequently enters syncronizedMethodB() .并且由于 HB 是可传递的,因此在syncronizedMethodA()执行的操作对于随后进入syncronizedMethodB()任何线程都是可见的。

On the other hand, no happens-before relation exists between the release of the monitor in syncronizedMethodA() and subsequent actions performed in notSynchronizedMethod() by another thread.在另一方面,没有之前发生的显示器的在释放之间存在关系syncronizedMethodA()和在执行后续操作notSynchronizedMethod()由另一个线程。 Therefore, there are no guarantees that the writes in syncronizedMethodA() are made visible to another thread's reads in notSynchronizedMethod() .因此,有没有保证,在写syncronizedMethodA()是由可见的另一个线程的读取notSynchronizedMethod()

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

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