ここにはたくさんの質問があります。それらを一度に1つずつ検討します。
参照の割り当てはアトミックですが、なぜInterlocked.Exchange(ref Object、Object)が必要なのですか?
参照の割り当てはアトミックです。Interlocked.Exchangeは、参照の割り当てだけを行いません。変数の現在の値を読み取り、古い値を隠し、新しい値を変数に割り当てます。これらはすべて不可分操作です。
私の同僚は、一部のプラットフォームでは、参照の割り当てがアトミックであることが保証されていないと述べました。私の同僚は正しかったですか?
いいえ。参照の割り当ては、すべての.NETプラットフォームでアトミックであることが保証されています。
私の同僚は誤った前提から推論しています。それは彼らの結論が間違っていることを意味しますか?
必ずしも。あなたの同僚は悪い理由であなたに良いアドバイスをしているかもしれません。おそらく、Interlocked.Exchangeを使用する必要がある他の理由があります。ロックフリープログラミングはめちゃくちゃ難しく、この分野の専門家によって支持されている確立された慣行から離れた瞬間、あなたは雑草の中にいて、最悪の種類の競合状態の危険を冒しています。私はこの分野の専門家でもあなたのコードの専門家でもないので、どちらの方法でも判断することはできません。
「揮発性フィールドへの参照は揮発性として扱われません」という警告が表示されます。これについてどう思いますか?
これが一般的に問題である理由を理解する必要があります。これにより、この特定のケースで警告が重要でない理由を理解できます。
コンパイラがこの警告を出す理由は、フィールドを揮発性としてマークすることは、「このフィールドは複数のスレッドで更新される予定です。このフィールドの値をキャッシュするコードを生成しないでください。また、このフィールドは、プロセッサキャッシュの不整合によって「時間的に前後に移動」することはありません。
(私はあなたがすでにすべてを理解していると思います。揮発性の意味とそれがプロセッサキャッシュセマンティクスにどのように影響するかを詳細に理解していない場合は、それがどのように機能するかを理解しておらず、揮発性を使用するべきではありません。ロックフリープログラム正しく理解するのは非常に困難です。偶然ではなく、プログラムがどのように機能するかを理解しているので、プログラムが正しいことを確認してください。)
ここで、揮発性フィールドにrefを渡すことにより、そのフィールドのエイリアスである変数を作成するとします。呼び出されたメソッドの内部では、コンパイラーは、参照に揮発性のセマンティクスが必要であることを知る理由はまったくありません。コンパイラーは、揮発性フィールドのルールを実装できないメソッドのコードを元気に生成しますが、変数は揮発性フィールドです。それはあなたのロックフリーロジックを完全に破壊する可能性があります。揮発性フィールドは常に揮発性セマンティクスでアクセスされるという前提が常にあります。それを揮発性として扱うことは意味がありません。常に一貫性を保つ必要があります。そうしないと、他のアクセスの一貫性を保証できません。
したがって、これを行うと、コンパイラは警告を発します。これは、慎重に開発されたロックフリーロジックを完全に台無しにする可能性があるためです。
もちろん、Interlocked.Exchangeは、揮発性フィールドを予期して正しいことを行うように作成されています。したがって、警告は誤解を招く可能性があります。私はこれを非常に後悔しています。Interlocked.Exchangeのようなメソッドの作成者が、「refを受け取るこのメソッドは変数に揮発性セマンティクスを適用するため、警告を抑制します」という属性をメソッドに設定できるメカニズムを実装する必要があります。おそらく、コンパイラの将来のバージョンでは、そうする予定です。