たとえば、データ オブジェクトがあるとします。
class ValueRef { double value; }
各データ オブジェクトがマスター コレクションに格納される場所:
Collection<ValueRef> masterList = ...;
ジョブのコレクションもあり、各ジョブにはデータ オブジェクトのローカル コレクションがあります (各データ オブジェクトは にも表示されますmasterList
)。
class Job implements Runnable {
Collection<ValueRef> neededValues = ...;
void run() {
double sum = 0;
for (ValueRef x: neededValues) sum += x;
System.out.println(sum);
}
}
使用事例:
for (ValueRef x: masterList) { x.value = Math.random(); }
ジョブ キューにいくつかのジョブを入力します。
スレッドプールを起こす
各ジョブが評価されるまで待ちます
注: ジョブの評価中、すべての値はすべて一定です。ただし、スレッドは過去にジョブを評価した可能性があり、キャッシュされた値を保持しています。
質問: 各スレッドが最新の値を認識できるようにするために必要な同期の最小量はどれくらいですか?
モニター/ロックの観点からの同期は理解していますが、キャッシュ/フラッシュの観点からの同期は理解していません (つまり、同期ブロックの開始/終了時にメモリ モデルによって何が保証されているか)。
私には、新しい値をメイン メモリにコミットするために値を更新するスレッドで 1 回同期し、新しい値が読み取られるようにキャッシュをフラッシュするためにワーカー スレッドごとに 1 回同期する必要があるように感じます。しかし、これを行う最善の方法がわかりません。
私のアプローチ:グローバル モニターを作成します。次に、マスター リストを更新しながらstatic Object guard = new Object();
同期します。guard
最後に、スレッド プールを開始する前に、プール内のスレッドごとに 1 回guard
、空のブロックで同期します。
それは本当にそのスレッドによって読み取られた値の完全なフラッシュを引き起こしますか? それとも、同期ブロック内で触れた値だけですか? その場合、空のブロックの代わりに、各値をループで 1 回読み取る必要がありますか?
御時間ありがとうございます。
編集:私の質問は、同期ブロックを終了すると、(その時点以降の)最初の読み取りはすべてメインメモリに移動するのでしょうか? 何を同期したかに関係なく?