技術的でないタイトルで申し訳ありませんが、それは私の質問をうまく要約していると思います。私が正しく読んだものを解釈すると、同期ブロックは(他の結果を除いて)すべての変数をメインメモリとの間で更新します(同期ブロック内で明示的にアクセスされていない変数でも、それらの「親」のみ?) 。たとえば、このスタックオーバーフローの質問の答えを引用します(私はそれを文脈から外しました、後でそれに戻ります):
メモリバリアは、無関係なものも含め、すべてのメモリ参照に適用されます。
これを正しく解釈できるかどうかの確認が必要です。私は2つのスレッド(threadA、threadB)を持っています。次のコードを検討してください。
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から呼び出され、ThreadAinitA()
から呼び出さoperationA()
れます。(これは、 ThreadBが作成される前でも呼び出されるため、同時実行されることに注意してください。)また、配列のコピーを返さないのには十分な理由があることに注意してください(いいえ、threadBはその要素を変更したくないので、理由は、現在は関係のない私のソフトウェアの外部要件です)。initA()
getterB()
operationA()
getterB()
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()
ますか?)引用されたステートメントは、無関係のキャッシュされたコピーがメインメモリからも更新されると述べています。私はこれを100%無関係に解釈する方法ではありません(ロックに使用される変数とは無関係ですか?または同期されたブロック全体とは無関係ですか?)。私は引用を文脈から外したことを知っています、そしてそれは別のスタックオーバーフローの質問なので、そこにコメントを追加しました。ですから、私の質問がそこで(またはここで-私は気にしません)答えられれば幸いです。
anArray
オブジェクトの配列(プリミティブ型ではない)の場合、答えに違いはありますか?さらに進んで、それが配列ではなく、他のクラスへの参照を含むクラスである場合はどうなるでしょうか。(つまり、他のオブジェクトを参照するオブジェクトであり、によって返されたオブジェクトを介して含まれているオブジェクトにアクセスしますgetterB()
)。threadBは、これらの含まれている参照の最新のコピーを使用しますか、それとも 独自のローカルキャッシュコピーを使用しますか(コンテナオブジェクトのみを更新し、含まれている参照自体は更新しないため)。getterB()