Java中synchronized/volatile的可变可见性影响的程度如何
根据“实践中的Java并发性”: 当B执行由同一锁保护的同步块时,A在同步块中或之前所做的一切都对B可见 及 易失性变量的可见性影响超出了易失性变量本身的值。当线程A写入易失性变量,然后线程B读取该变量时,在写入易失性变量之前对A可见的所有变量的值在读取易失性变量后对B可见 我不清楚的是,一切和所有变量是什么意思?它真的意味着一切吗?如果我们有这样的课程: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
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锁定同一个锁之前发生。