繁体   English   中英

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

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

根据“Java并发实践”:

A 在同步块中或同步块之前执行的所有操作对 B 执行由同一锁保护的同步块时,它都是可见的

volatile 变量的可见性影响超出了 volatile 变量本身的值。 当线程 A 写入一个 volatile 变量,随后线程 B 读取同一个变量时,在写入 volatile 变量之前对 A 可见的所有变量的值在读取 volatile 变量后对 B 可见

我不清楚的是一切所有变量的含义是什么? 它的字面意思是一切吗? 如果我们有一个这样的类:

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]
  }
}

如果我们调用syncronizedMethodA()在一个线程,然后调用syncronizedMethodB()notSyncronizedMethod()在另一个线程,假设时间顺序stritly保证下,将调用syncronizedMethodB()notSyncronizedMethod()通过使用最新的变量值设定syncronizedMethodA() 我确定 a 的值对于syncronizedMethodB()是可以的,但是对于像 array[3]、myClass.a 甚至 myClass.myClass.array[3] 这样的引用类型的元素呢? 值由同步方法更新的notSyncronizedMethod()怎么样?

为了弄清楚提供了哪些可见性保证,您需要更好地理解 Java 内存模型,更具体地说,在 JMM 的上下文中,先发生什么意味着什么。 JMM 将发生的事情描述为动作,例如,正常读取和写入、易失性读取和写入、锁定、解锁等。

JMM 中有一些规则可以确定一个动作何时发生 - 在另一个动作之前。 与您的情况相关的规则如下:

单线程规则:在给定的线程中,如果 A 在程序顺序中先于 B,则动作 A 发生在动作 B 之前。

监视器锁定规则(同步):给定监视器的解锁发生在同一监视器上的后续锁定之前。

重要的是要知道happens-before是可传递的,即如果hb(a, b) 和hb(b, c),那么hb(a, c)。

在您的示例中,一个线程在退出syncronizedMethodA()时释放监视器,而另一个线程随后在进入syncronizedMethodB()时获取监视器。 这是一个发生在之前的关系。 并且由于 HB 是可传递的,因此在syncronizedMethodA()执行的操作对于随后进入syncronizedMethodB()任何线程都是可见的。

在另一方面,没有之前发生的显示器的在释放之间存在关系syncronizedMethodA()和在执行后续操作notSynchronizedMethod()由另一个线程。 因此,有没有保证,在写syncronizedMethodA()是由可见的另一个线程的读取notSynchronizedMethod()

暂无
暂无

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

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