言ってやるが、私は、データオブジェクトを持っています。また、スレッドプール、共有データ、Javaの同期
Collection<ValueRef> masterList = ...;
私は:各データオブジェクトは、マスター・コレクションに格納されて
class ValueRef { double value; }
各ジョブにデータオブジェクトのローカルコレクションがある(各データオブジェクトは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(); }
一部のジョブとジョブキューを移入します。
ウェイクアップ各ジョブが
注意して評価されるまで、スレッドプール
待ち:職務評価の間に、すべての値はすべて一定です。しかし、スレッドは、過去にジョブを評価し、キャッシュされた値を保持する可能性があります。
質問:各スレッドが最新の値を確認するために必要な同期の最小量はいくらですか?
私は、モニター/ロックパースペクティブから同期を理解していますが、キャッシュ/フラッシュの観点から同期しているとは分かりません(つまり、同期ブロックの入力/終了時のメモリモデルによって保証されているもの)。
私には、メインメモリに新しい値をコミットするために値を更新するスレッドと、新しい値が読み込まれるようにキャッシュをフラッシュするワーカースレッドごとに一度同期する必要があるように感じます。しかし、私はこれをどうやって行うのが最善かわかりません。
私のアプローチ:グローバルモニタを作成します。static Object guard = new Object();
次に、マスターリストを更新しながらguard
で同期します。最後に、スレッドプールを開始する前に、プール内のスレッドごとに1度、空のブロックにguard
を同期させます。
実際には、そのスレッドが読み取った値が完全にフラッシュされますか?または、同期ブロック内の値だけをタッチしますか?この場合、空のブロックではなく、ループ内で各値を一度読み取る必要がありますか?
お時間をいただきありがとうございます。
編集:私は、同期ブロックを終了すると、最初のすべての読み取り(その時点の後)はメインメモリに行くのですか?私が同期したものに関係なく?
揮発性キーワード – ControlAltDel
を利用するためのほぼ完璧な場所のようですが、私は一度書く(事実上一定)が、潜在的に何百万回も読んでいます。揮発性は決してローカルにキャッシュされません。毎回スレッドプールを作成した場合、コードは(以前のキャッシュが存在しないため)細かいw/o同期/ volatileで動作します。 –
私はここに揮発性の必要性が表示されません。 ValueRefが効果的に不変の場合、実際には不変にしてください。ダブルを使用します。スケジュールされる前にジョブごとに新しいコレクションを作成し、unmodifiableCollectionでラップします(リマインダーと同様)。あなたは何の問題を考えますか? –