Java中synchronized/volatile的可变可见性影响的程度如何

Java中synchronized/volatile的可变可见性影响的程度如何,java,concurrency,synchronization,volatile,Java,Concurrency,Synchronization,Volatile,根据“实践中的Java并发性”: 当B执行由同一锁保护的同步块时,A在同步块中或之前所做的一切都对B可见 及 易失性变量的可见性影响超出了易失性变量本身的值。当线程A写入易失性变量,然后线程B读取该变量时,在写入易失性变量之前对A可见的所有变量的值在读取易失性变量后对B可见 我不清楚的是,一切和所有变量是什么意思?它真的意味着一切吗?如果我们有这样的课程: class MyClassA{ int a; int[] array = new int[10]; MyClassB myCla

根据“实践中的Java并发性”:

当B执行由同一锁保护的同步块时,A在同步块中或之前所做的一切都对B可见

易失性变量的可见性影响超出了易失性变量本身的值。当线程A写入易失性变量,然后线程B读取该变量时,在写入易失性变量之前对A可见的所有变量的值在读取易失性变量后对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()
,假设严格保证了时间顺序,则将调用
syncronizedMethodB()
notSyncronizedMethod()
使用由
syncronizedMethodA()
设置的最新变量值。我确信a的值对于syncronizedMethodB()来说是可以的,但是像array[3]、myClass.a甚至myClass.myClass.array[3]这样的引用类型的元素呢?使用syncronized方法更新值的
notSyncronizedMethod()
如何?

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

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

单线程规则:在给定线程中,如果程序顺序中a在B之前,则动作a发生在动作B之前

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

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

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

另一方面,在另一个线程在
syncronizedMethodA()
中释放监视器和在
notSynchronizedMethod()
中执行后续操作之间存在关系之前,不会发生任何情况。因此,不能保证
syncronizedMethodA()
中的写入对
notSynchronizedMethod()
中另一个线程的读取可见

Re,“它真的意味着一切吗?”是的。如果线程A在释放某个锁之前更新某个变量(任何变量),那么从线程B的角度来看,该更新保证在线程B锁定同一个锁之前发生。