8

Java 5 以降、volatileキーワードにはリリース/取得セマンティクスがあり、副作用を他のスレッドから見えるようにします (非揮発性変数への代入を含む!)。たとえば、次の 2 つの変数を使用します。

int i;
volatile int v;

iは通常の非揮発性変数であることに注意してください。次のステートメントを実行するスレッド 1 を想像してください。

i = 42;
v = 0;

その後、スレッド 2 は次のステートメントを実行します。

int some_local_variable = v;
print(i);

Java メモリ モデルによると、vスレッド 1 での書き込みとそれに続くスレッド 2 での読み取りによりv、スレッド 2 はiスレッド 1 で実行された書き込みを認識できるため、値 42 が出力されます。

私の質問はvolatile、C# で同じリリース/取得セマンティクスを持っていますか?

4

2 に答える 2

16

C# の「volatile」のセマンティクスは、 C# 6.0 仕様のセクション 7.10 および 14.5.4 で定義されています。ここで再現するのではなく、仕様を調べてから、「揮発性」を使用するのは複雑すぎて危険であると判断し、ロックの使用に戻ることをお勧めします。それが私がいつもしていることです。

C# 6.0 仕様の「 7.10 実行順序」および「14.5.4 揮発性フィールド」を参照してください。


C# 5.0 仕様では、「3.10 実行順序」および「10.5.3 揮発性フィールド」を参照してください。

于 2011-06-29T20:01:06.177 に答える
7

そうですね、( への書き込みにより)が 42 として読み取られることが保証されると思います。 some_local_variable0vi

トリッキーな部分は、「後で」です。一般に、揮発性は「フラッシュ」書き込みの観点から語られますが、それは仕様 (Java または C#) で実際に定義されている方法ではありません。

C# 4 言語仕様のセクション 10.5.3 から:

不揮発性フィールドの場合、命令を並べ替える最適化手法は、lock-statement (§8.12) によって提供されるような同期なしでフィールドにアクセスするマルチスレッド プログラムで、予期しない予測不可能な結果につながる可能性があります。これらの最適化は、コンパイラ、ランタイム システム、またはハードウェアによって実行できます。volatile フィールドの場合、このような並べ替えの最適化は制限されています。

  • 揮発性フィールドの読み取りは、揮発性読み取りと呼ばれます。揮発性読み取りには「取得セマンティクス」があります。つまり、命令シーケンスでそれ以降に発生するメモリへの参照の前に発生することが保証されています。
  • 揮発性フィールドの書き込みは、揮発性書き込みと呼ばれます。揮発性書き込みには「解放セマンティクス」があります。つまり、命令シーケンス内の書き込み命令より前のメモリ参照の後に発生することが保証されています。

次に、あなたのものと非常に似ている例がありますが、揮発性変数から読み取られた値を条件としています。

Eric のように、私自身も volatile に依存することは絶対に避けたいと思います。推論するのは難しく、世界のジョー・ダフィー/スティーブン・トゥーブに任せるのが最善です.

于 2011-06-29T20:00:30.933 に答える