ミューテックス
ミューテックス (Mutex) とは、コンピュータプログラミングにおける技術用語。クリティカルセクションでアトミック性を確保するための同期機構の一種である。Mutexという語はMUTual EXclusion(相互排他)の省略形となっている。
目次
概要
セマフォをクリティカルセクションの排他制御に用いる時、セマフォでは(初期値が1でなければ)複数のタスクがクリティカルセクションへ入ることを許可するのに対し、ミューテックスでは同時に一つのタスクしかクリティカルセクションに入ることを許されない(ここで言うタスクとは、スレッドまたはプロセスを指す)。挙動はセマフォ変数の初期値を1にする事と等価。このようなタスク優先度とリンクしないミューテックスを、バイナリセマフォと呼ぶ場合もある。
狭義には、ミューテックスの場合にそれをロック(P操作)したタスクのみがアンロック(V操作)できるのに対して、セマフォではその様な制約はない。また、ミューテックスには、優先度逆転を防止するための優先度継承 (Priority Inheritance) 機能や、デッドロックを防止するための優先度上限プロトコル(Priority Ceiling Protocol)機能などが拡張されていることがある。
一般的には異なるタスク間で排他制御を行いたい時に使用するが、マルチタスク環境ではプロセスの多重起動を防止する用途にも使える。
ミューテックスの起源はディジタル・イクイップメント・コーポレーションにおける、機材の使用管理が由来である。使用可能な機材の上には小さな旗が置かれ、その旗を手にいれた者がその機材の使用権利を獲得する。この排他制御からヒントを得たVMS開発チームはVMSの排他制御にミューテックスを実現した。そしてその技術はデヴィッド・カトラーを筆頭としたVMS開発チームと共にMicrosoft Windows NTにも移された(著:戦うプログラマーより)。
POSIXのmutexは、VMSやWin32と違い、自らP操作したmutexをさらにP操作するとデッドロックを起こす(そして誰もロックを解除できなくなる)。その為若干取り扱いは不便である。
ミューテックスの使用
ミューテックス機構を使用するには、プログラムでミューテックスオブジェクトを作成する必要がある。ミューテックスオブジェクトはシグナル及び非シグナルの二つの状態を持ち、それぞれミューテックスオブジェクトが所有可能及び所有不可能である事を表す。
クリティカルセクションへの進入
クリティカルセクションに入るにはミューテックスオブジェクトの所有を行う(所有というのはインスタンスの作成という意味ではなく、クリティカルセクションへの進入権を得るという事である)。この時、ミューテックスオブジェクトの状態によってクリティカルセクションに入れるかどうかが異なる。
- シグナル状態
- すぐにクリティカルセクションに入る事ができ、処理を続行できる。この時、ミューテックスオブジェクトはシグナル状態から非シグナル状態になり、これによって後続のタスクが同時にクリティカルセクションに入る事を防ぐ。
- 非シグナル状態
- クリティカルセクションに入る事はできず、通常はシグナル状態になるまで(ミューテックスオブジェクトが解放されるまで)タスクは待機状態になる。実装によってはタイムアウトを指定する事ができ、指定した期間内にミューテックスオブジェクトが解放されなければ所有は失敗し、タスクに処理が戻る。この時、タスクは所有が失敗した事を感知し、処理を中断するべきである。
クリティカルセクションからの離脱
クリティカルセクションから抜ける時はミューテックスオブジェクトを解放する。解放されたミューテックスオブジェクトは非シグナル状態からシグナル状態に戻り、これによって後続のタスクはミューテックスオブジェクトを所有する事が可能になる。
環境毎の使用法
Windows
プロセス間の場合
プロセス間の排他制御には、以下の方法がある。
- Mutex - ミューテックスオブジェクトの初期化に
CreateMutex()
Win32 API関数を使う。 - Metered Section -
CreateMeteredSection()
を使って作成する。Mutexより高速である。但しこれは Win32 APIでなく、自作する物である。[1][2]
プロセス内の場合
プロセス間でミューテックスを共有する必要がない場合は、
- Critical Section - クリティカルセクションオブジェクトが使える。初期化には
InitializeCriticalSection()
Win32 API関数を使う。Mutexより高速である。 - Mutex - 無名のミューテックスオブジェクトを使う。
.NET Framework
プロセス間の場合
System.Threading.Mutex
クラスを使う。
プロセス内の場合
C#では lock
ステートメント、Visual Basic .NETでは SyncLock
ステートメントで、クリティカルセクションをミューテックスにより相互排他ロックが可能である。
Java
Javaでは、ミューテックスが言語仕様に組み込んであり、synchronized
を使う。任意のオブジェクトをミューテックスオブジェクトとして使用できる。
μITRON仕様
3.0仕様以前には、ミューテックスは存在しない。広義のミューテックスはセマフォで代用することは可能であるが、優先度逆転を防げない。 しかしながら、3.0仕様準拠OSでも、実装独自に優先度逆転を防止できるミューテックスが存在する可能性はある。
4.0仕様以降では、優先度上限および優先度継承をサポートするミューテックスオブジェクトが追加された。しかし、スタンダードプロファイルには含まれておらず、実質オプション扱いである。