MSDN フォーラム「Boolean変数をスレッドセーフに設定する方法について」 より。
当然、Interlocked はかなり軽量だ。Win32 Interlocked API の実行は少量のCPU サイクルで済み、且つカーネルモードへ遷移しない。Interlocked クラスは Win32 Interlocked API を使って実現されている(たぶん)。
対して Monitorは、C#、VB.NET による言語サポートがあり、それぞれ lock、SyncLock というステートメントを使って簡単に使える。Monitor クラスは要はクリティカルセクションの事だ。
クリティカルセクションはカーネルモードへ遷移するので、Interlocked API に比べればコストはかなりかかる(カーネルモードへ遷移するには相当 CPU サイクルを使う)。…というのは正確ではなく、通常はスピンロックを使用して数回(数千回)リソースを獲得しようと試み、即カーネルモードに遷移する事はしないので、軽量である場合がある。
Win32 API を使ってのクリティカルセクションではスピンカウントを設定して何度スピンロックするかを開発者が設定する事が可能だが、Monitor クラスにはスピンカウントを設定できるメソッドは見当たらない。lock、SyncLock ステートメントを使っても当然スピンカウントの設定はできない。デフォルトでスピンカウントが決まっているのかもしれない。
…という事で検証に入りたいと思うが、シングルプロセッサではスピンカウントを設定しても無視される。つまりシングルプロセッサでは Monitor クラスは常にスピンロックを行わないで即カーネルモードへ遷移する。
つい最近やっとデュアルコアプロセッサを手に入れたので検証できる…が、それはまたの機会にしたいと思う。
この辺りの知識は、Advanced Windows
に書いてある事そのままだ。
.NET Framework の時代に入ってこういう類の API を直接使う事がなくなったとしても、せめて知識だけは Windows プログラマならば当然持っていなければならないだろう。