特定のアプリケーションに対して、いくつかの実装は他のものより優れていますか?自分でロールアウトして獲得できるものはありますか?
Wikipediaの Test-and-set 機械命令の説明を確認してください。これは、機械レベルで原子操作がどのように達成されるかを暗示しています。ほとんどの言語レベルのミューテックス実装は、テストと設定などのマシンレベルのサポートに依存していると想像できます。
Adamskiのtest-and-set
提案、「高速ユーザー空間ミューテックス」または futexes の概念も参照する必要があります。
フューテックスには、uncontendedミューテックスをロックまたはロック解除する一般的な場合にカーネルシステムコールを必要としないという望ましい特性があります。これらの場合、ユーザーモードコードはアトミック 比較とスワップ(CAS) 操作を使用して、ミューテックスをロックまたはロック解除します。
CASが失敗すると、mutexが競合し、カーネルシステムコール-sys_futex
Linuxの場合-mutexを待機する(ロックの場合)か、他のスレッドをウェイクアップする(ロック解除の場合)ために使用する必要があります。
これを自分で実装することに真剣に取り組んでいる場合は、Ulrich Drepperの paper も読んでください。
mutex は、オペレーティングシステムのカーネルで実行し、周囲のコードの量をできる限り短くすることが好ましいため、別のプロセスへのタスク切り替え中の切断を回避できます。したがって、正確な実装は少し秘密です。しかし、それは複雑ではありません。これは基本的に、取得および設定するブールフィールドを持つオブジェクトです。
基本的なミューテックスロジックの周りには、オブジェクトにラップするラッパーがあります。その後、カーネルの外部で使用できるようにするラッパーオブジェクトが増えます。そして、.NETで使用できるようにする別のラッパー。そして、何人かのプログラマーは、論理的なニーズに合わせて、これに関する独自のラッパーコードを作成します。ラッパーの周りのラッパーは、本当にそれらを暗い領域にします。
さて、mutexの内部に関するこの基本的な知識があれば、カーネルとその下のハードウェアに依存する1つの実装を使用することを望みます。これらが最も信頼性が高いでしょう。 (ハードウェアがこれらをサポートしている場合。)使用しているミューテックスがこのカーネル/ハードウェアレベルで動作しない場合、信頼性はありますが、代替手段がない限り、使用しないことをお勧めします。
私の知る限り、Windows、Linux、および.NETはすべて、カーネル/ハードウェアレベルでミューテックスを使用します。
私がリンクしたウィキペディアのページでは、内部ロジックと可能な実装について詳しく説明しています。ミューテックスはハードウェアによって制御され、ミューテックスの取得/設定全体が indivisible step であることが望ましい。 (システムがタスクを途中で切り替えないようにするためだけに。)
Interlocked.CompareExchange
は、スピンロックを実装するのに十分です。しかし、正しいことをするのはかなり難しいです。関連する微妙な例については、 Joe Duffyのブログ を参照してください。
アトミックにロックを示すためのアセンブリの一部:
; BL is the mutex id
; shared_val, a memory address
CMP [shared_val],BL ; Perhaps it is locked to us anyway
JZ .OutLoop2
.Loop1:
CMP [shared_val],0xFF ; Free
JZ .OutLoop1 ; Yes
pause ; equal to rep nop.
JMP .Loop1 ; Else, retry
.OutLoop1:
; Lock is free, grab it
MOV AL,0xFF
LOCK CMPXCHG [shared_val],BL
JNZ .Loop1 ; Write failed
.OutLoop2: ; Lock Acquired