マルチスレッドに関する章/本をすべて読めば答えを見つけることができますが、もっと迅速な答えが欲しいです。(私はこのスタックオーバーフローの質問が似ていることを知っていますが、十分ではありません.)
次のクラスがあるとします。
public class TestClass {
private int someValue;
public int getSomeValue() { return someValue; }
public void setSomeValue(int value) { someValue = value; }
}
このクラスのインスタンスにアクセスする 2 つのスレッド (A と B) があります。次のシーケンスを検討してください。
- A: getSomeValue()
- B: setSomeValue()
- A: getSomeValue()
そうしないと、3 番目のステップで最新の値が返されない可能性があります (A にはキャッシュされた値がある可能性があるため)。これは正しいです?
2 番目のシナリオ:
- B: setSomeValue()
- A: getSomeValue()
この場合、A は常に正しい値を取得します。これは、これが最初のアクセスであり、キャッシュされた値をまだ取得できないためです。これは正しいですか?
クラスが2番目の方法でのみアクセスされる場合、揮発性/同期は必要ありませんか?
この例は単純化されたものであり、実際には複雑なクラスの特定のメンバー変数とメソッドについて疑問に思っていることに注意してください。クラス全体についてではありません (つまり、どの変数を揮発性にするか、同期アクセスにする必要があるか)。要点は次のとおりです。より多くのスレッドが特定のデータにアクセスする場合、必ず同期アクセスが必要ですか、それともアクセス方法 (順序など) に依存するのでしょうか?
コメントを読んだ後、別の例で混乱の原因を提示しようとしました。
- UI スレッドから:
threadA.start()
- threadA が を呼び出し
getSomeValue()
、UI スレッドに通知します。 - UI スレッドはメッセージを (メッセージ キューで) 取得するため、以下を呼び出します。
threadB.start()
- threadB が を呼び出し
setSomeValue()
、UI スレッドに通知します。 - UI スレッドはメッセージを取得し、threadA に通知します (何らかの方法で、たとえばメッセージ キュー)。
- threadA 呼び出し
getSomeValue()
これは完全に同期された構造ですが、なぜこれは、threadA がステップ 6 で最新の値を取得することを意味するのでしょうか? (someValue
揮発性でない場合、またはどこからでもアクセスしたときにモニターに入れられない場合)