5

ダブルチェック ロックが正しく機能するためには、変数を宣言する必要がvolatileあり、オブジェクトの初期化を同期するだけでは不十分であることは、Java プログラマの間ではよく知られています。

この認識はおそらく、volatileキーワードのセマンティクスが 1.5 で変更され、「前に発生する」関係を含むようになったためです。少なくとも部分的には、二重チェックのロックを安全にするためです。私が理解していることから、「前に起こる」関係は、揮発性変数に書き込むと、スレッド内のすべてのキャッシュされた変数がメインメモリに書き込まれ、揮発性変数から読み取った後、すべてのキャッシュされた変数は古いと見なされ、揮発性変数への書き込みの前に書き込まれたすべてが、その変数からの後の読み取りの「前に発生する」ことが保証されるように、メインメモリから再読み取りします。

スタック オーバーフローは、C# の場合、ダブルチェック ロックは不要であると考えているようですvolatile(これは特定の CPU または Microsoft の実装に固有のものである可能性があることに注意しているにもかかわらず)、Java のsynchronizedステートメントのセマンティクスはC#のステートメントとまったく同じlockであると考えています。このステートメントは、Java で特定されたのと同じ問題が C# にも存在することを示唆しています。

では・・・どれが正しい?C# でのダブルチェック ロックは、実際には Java よりも危険性が低いですか? もしそうなら、どの言語セマンティクスがそれを実現するのに違いますか?

そうでない場合、具体的に何が問題になる可能性がありvolatileますか? volatileC#のセマンティクスは、Java のような "前に発生する" 関係を確立しvolatileますか?

4

1 に答える 1

3

MSDNから: 「volatile キーワードは、同時に実行されている複数のスレッドによってフィールドが変更される可能性があることを示します。volatile と宣言されたフィールドは、単一のスレッドによるアクセスを想定したコンパイラの最適化の対象ではありません。これにより、ほとんどの-現在までの値は常にフィールドに存在します。」

したがって、volatile は、変数の値を複数のスレッドから変更する場合にのみ役立ちます。同じロック オブジェクトを使用して共有リソースにアクセスするコード領域を lock() すると、それらのコード領域に同時にアクセスできるスレッドは 1 つだけであることが保証されます。ロック オブジェクトを変更しない限り、volatile は必要ありません (これは非常に悪い考えです)。 .

于 2014-04-15T00:18:36.050 に答える