C# と Java の両方で、
* volatile 読み取りには取得セマンティクスが
ある
* volatile 書き込みにはリリース セマンティクスがあると定義されてい
ます。私の質問は次のとおりです。
- これが揮発性を定義する唯一の正しい方法ですか。
- そうでない場合、セマンティクスが逆になった場合、物事は大きく異なりますか。つまり、
- 揮発性読み取りには解放セマンティクスがあります
- volatile 書き込みにはセマンティクスの取得があります
C# と Java の両方で、
* volatile 読み取りには取得セマンティクスが
ある
* volatile 書き込みにはリリース セマンティクスがあると定義されてい
ます。私の質問は次のとおりです。
- これが揮発性を定義する唯一の正しい方法ですか。
- そうでない場合、セマンティクスが逆になった場合、物事は大きく異なりますか。つまり、
- 揮発性読み取りには解放セマンティクスがあります
- volatile 書き込みにはセマンティクスの取得があります
セマンティックの背後にある理由は、アクションに関して指定されているJava メモリ モデルvolatile
に根ざしています。
Java メモリ モデルは、Java プログラムで発生する可能性のあるアクションに対して、事前発生と呼ばれる部分的な順序付けを定義します。通常、スレッドが他のアクションの結果を確認できるという保証はありません。
2 つのアクションAとBがあるとします。アクション B を実行するスレッドがアクション A の結果を確認できることを保証するには、A と B の間に事前発生関係が存在する必要があります。
正しく同期されていないプログラムでは、データ競合が発生する可能性があります。変数が >1 スレッドによって読み取られ、>= 1 スレッドによって書き込まれると、データ競合が発生しますが、読み取りおよび書き込みアクションは、先行発生順序付けによって順序付けられません。
したがって、正しく同期されたプログラムにはデータ競合がなく、プログラム内のすべてのアクションは固定された順序で発生します。
したがって、通常、アクションは部分的にのみ順序付けられますが、以下の間には全体的な順序もあります。
これらのアクションは完全に順序付けられています。
これにより、「後続の」ロックの取得と揮発性変数の読み取りという観点から、事前発生を説明することが賢明になります。
ご質問について:
volatile
これは、2 つのスレッドが共通のロックを使用して同期するときの事前発生関係を示しています。スレッド A 内のすべてのアクションは、スレッド B 内のアクションと同様に、プログラム順序規則 によって順序付けられます。A がロック M を解放し、B が続いて M を取得するため、ロックを解放する前の A 内のすべてのアクションは、B 内のアクションの前に順序付けられます。ロックを取得した後。2 つのスレッドが異なるロックで同期する場合、それらの間のアクションの順序については何も言えません。2 つのスレッドのアクション間には、事前発生の関係はありません。
取得/解放セマンティクスの力は、他のスレッドが volatile フィールド自体の新しく書き込まれた値をどのくらい早く確認するかということではなく、さまざまなスレッド間で volatile 操作が事前発生関係を確立する方法にあります。スレッド A が volatile フィールドを読み取り、別のスレッド B でそのフィールドに書き込まれた値を確認した場合、スレッド A は、スレッド B が別の変数 (揮発性であるとは限らない) に書き込まれた値を、それが実行した時点より前に確認することも保証されます。揮発性書き込み。これはキャッシュのフラッシュのように見えますが、volatile を読み取るスレッドの観点からすると、volatile フィールドに触れない他のスレッドには、B に関する順序保証がなく、以前の不揮発性書き込みの一部が表示される可能性がありますが、コンパイラ/JIT がとても傾いています。
モニターの取得/解放は、誘導された発生前の関係によって同様に特徴付けられます。つまり、モニターの解放前の 1 つのスレッドによるアクションは、別のスレッドによる同じモニターの後続の取得後に表示されることが保証されます。揮発性は、モニター同期と同じ順序保証を提供しますが、ブロッキングはありません。