ミューテックスとは
ミューテックス(Mutex = MUTual EXclusion)とは排他制御を行う上で用いられる概念のひとつ。 ミューテックスは、ミューテックス(=排他区間)へ入ることを要求するP操作、ミューテックスから出ることを通知するV操作から構成される。 ミューテックスは同時に1つの処理しか排他区間に入ることを許可しないため、カウンタの初期値が1であるセマフォと同義である。 セマフォについての詳細はSystem.Threading.Semaphoreにて解説している。
.NET FrameworkにおけるMutex
基本的にはカウンタの初期値が1に固定されたSystem.Threading.Semaphoreと同じ。 名前付きでMutexインスタンスを生成すると、オペレーティングシステム全体から参照できる(プロセス間で共有できる)システムミューテックスとなり、名前なしでMutexインスタンスを生成すると、プロセス内でのみ参照できるローカルミューテックスとなる。
ミューテックスに入るにはWaitOne()、ミューテックスから出るにはReleaseMutex()を呼ぶ。 ただし、Semaphore.Release()とは異なり、ReleaseMutex()はWaitOne()したスレッドからしか呼び出すことが許可されない。 つまり、ミューテックスに入ったスレッド以外はミューテックスから出ることが出来ない(他のスレッドからは操作できない)。 ミューテックスに入っている処理(スレッド)がない場合、ミューテックスは「シグナル状態」(signaled)となる。 ミューテックスがシグナル状態になると、WaitOne()でブロックされている処理はミューテックスに入ることができるようになる。
システムミューテックスの場合ミューテックスには「所有権」という概念があり、システムミューテックスを生成したスレッドは「所有権」を持つことができる。 ミューテックスの所有権を持ったスレッドが終了した場合、ミューテックスは「放棄された状態」(abandoned)となる。 このとき、ミューテックスはシグナル状態となるが、他のスレッドがミューテックスに入ろうと待機(WaitOne)していた場合、そのスレッドではAbandonedMutexExceptionが発生する。
「所有権」の有無はインスタンスの生成時に指定できる(初期所有権)。 初期所有権を付与しなかった場合は、システムミューテックスを生成したスレッドが終了した後に他のスレッドが放棄されたミューテックスに入ろうとしても、AbandonedMutexExceptionは発生しない。
主なコンストラクタ
- Mutex()
- 名前なしミューテックスのインスタンスを生成する。
- Mutex(bool initiallyOwned, string name)
- 初期所有権の有無、ミューテックスの名前を指定してインスタンスを生成する。
- Mutex(bool initiallyOwned, string name, out bool createdNew)
- 初期所有権の有無、ミューテックスの名前を指定してインスタンスを生成する。
新しく名前付きミューテックスを作成した場合はcreatedNewにtrue、すでに同名の名前付きミューテックスが存在している場合はfalseがセットされる。
主なメソッド
- static Mutex OpenExisting(string name)
- すでに作成されている名前付きミューテックスを取得する。 取得できない場合、存在しない場合は、WaitHandleCannotBeOpenedExceptionがスローされる。
- bool WaitOne()
- ミューテックスに入る(P操作)。 すでに他のスレッドがミューテックスに入っている場合は、ReleaseMutex()が呼ばれる(V操作が行われる)まで処理がブロックされる。
- void ReleaseMutex()
- ミューテックスから出る(V操作)。
- void Close()
- インスタンスが保持しているリソースを解放する。
主な呼び出し順序
ローカルミューテックスの場合。
- new Mutex()
- WaitOne()
- Release()
- Close()
システムミューテックスの場合。
- 新しく生成する場合はnew Mutex()、既に生成されたものを参照する場合はMutex.OpenExisting()
- WaitOne()
- Release()
- Close()
使用例
システムミューテックスを生成し、排他区間に対して複数のプロセスから同時にアクセスを試みる。
上記プログラムを5プロセス同時に実行した場合の動作例。
Monoでは、環境変数MONO_ENABLE_SHMをセットして共有メモリの使用を有効にしないと名前付きミューテックスを使用できない。