ダブルチェック ロックが正しく機能するためには、変数を宣言する必要がvolatile
あり、オブジェクトの初期化を同期するだけでは不十分であることは、Java プログラマの間ではよく知られています。
この認識はおそらく、volatile
キーワードのセマンティクスが 1.5 で変更され、「前に発生する」関係を含むようになったためです。少なくとも部分的には、二重チェックのロックを安全にするためです。私が理解していることから、「前に起こる」関係は、揮発性変数に書き込むと、スレッド内のすべてのキャッシュされた変数がメインメモリに書き込まれ、揮発性変数から読み取った後、すべてのキャッシュされた変数は古いと見なされ、揮発性変数への書き込みの前に書き込まれたすべてが、その変数からの後の読み取りの「前に発生する」ことが保証されるように、メインメモリから再読み取りします。
スタック オーバーフローは、C# の場合、ダブルチェック ロックは不要であると考えているようですvolatile
(これは特定の CPU または Microsoft の実装に固有のものである可能性があることに注意しているにもかかわらず)、Java のsynchronized
ステートメントのセマンティクスはC#のステートメントとまったく同じlock
であると考えています。このステートメントは、Java で特定されたのと同じ問題が C# にも存在することを示唆しています。
では・・・どれが正しい?C# でのダブルチェック ロックは、実際には Java よりも危険性が低いですか? もしそうなら、どの言語セマンティクスがそれを実現するのに違いますか?
そうでない場合、具体的に何が問題になる可能性がありvolatile
ますか? volatile
C#のセマンティクスは、Java のような "前に発生する" 関係を確立しvolatile
ますか?