抱歉标题不够技术化,但我认为它很好地总结了我的问题。如果我正确理解所读的内容,同步块(除其他后果外)将使所有变量更新到/从主内存中(即使那些在同步块中未明确访问的“父级”变量)。例如,引用this stackoverflow问题的答案(我将其摘出上下文,稍后再回到它):
内存屏障适用于所有内存引用,即使是无关的引用。
我需要确认我是否正确解释了这个问题。我有2个线程(线程A,线程B)。考虑以下代码:
正如您所看到的,在
内存屏障适用于所有内存引用,即使是无关的引用。
我需要确认我是否正确解释了这个问题。我有2个线程(线程A,线程B)。考虑以下代码:
public class SomeClass {
private final Object mLock = new Object();
private int[] anArray;
public void initA() {
synchronized(mLock) {
...
anArray = new int[...];
operationA();
}
}
public void operationA() {
synchronized(mLock) {
// Manipulating the ELEMENTS of anArray,
// e.g. in loops, etc.
anArray[i] = ...
}
}
public int[] getterB() {
synchronized(mLock) {
return anArray;
}
}
}
getterB()
是从 ThreadB 调用的,initA()
和 operationA()
是从 ThreadA 调用的。(请注意,initA()
甚至在创建 ThreadB 之前就被调用了,因此只有 getterB()
和 operationA()
是并发的。) 还要注意,我有充分的理由不返回数组的 副本 在 getterB()
中(不,threadB 不想 更改 其元素;原因是我的软件对外部要求,现在与此无关)。
threadB 执行以下操作:int[] anArray = aSomeClass.getterB(); // aSomeClass is an instance of SomeClass
if (anArray[i] == n) { ....... } // various operations
...
// various other operations that read the elements of anArray
正如您所看到的,在
getterB()
中,只有anArray
引用在内存屏障中被访问,而不是数组值本身。我的问题是:
threadB会看到最新的数组元素值吗?(即,在
getterB()
中,这些元素本身是否也从主内存中更新了?)引用的语句提到不相关的缓存副本也会从主内存中更新。我不确定如何解释这个“不相关”(是与用于锁定的变量无关还是与整个同步块无关?)。我知道我摘录了这句话,因为它是一个不同的stackoverflow问题,所以我添加了一个注释there。因此,如果我的问题在那里得到回答(或者在这里-我不在乎),我会很感激。
如果
anArray
是对象数组(而不是原始类型数组),答案有什么区别吗?更进一步,如果它不是数组,而是一个包含对其他类的引用的类呢?(即,一个引用其他对象的对象,并且通过getterB()
返回的对象访问这些包含的对象)。threadB会使用这些包含引用的最新副本,还是可能使用自己的本地缓存副本(因为getterB()
只更新了它们的容器对象,而不是这些包含的引用本身)?