ミューテックス

ミューテックス  とは、コンピュータプログラミングにおける技術用語。クリティカルセクションでアトミック性を確保するための排他制御や同期機構の一種である。「en」という語は「en」  の省略形である。ここでは、狭義の排他制御について述べる。

1. 概要
-----

セマフォをクリティカルセクションの排他制御に用いる時、セマフォでは複数のタスクがクリティカルセクションに入ることを許可するのに対し、ミューテックスでは同時に一つのタスクのみがクリティカルセクションに入ることを許可する。挙動はセマフォ変数の初期値を1にする事と等価。このようなタスク優先度とリンクしないミューテックスを、バイナリセマフォと呼ぶ場合もある。

狭義には、ミューテックスの場合にそれをロックしたタスクのみがアンロックできるのに対して、セマフォではその様な制約はない。また、ミューテックスには、優先度逆転を防止するための優先度継承  機能や、デッドロックを防止するための優先度上限プロトコル  機能などが拡張されていることがある。

一般的には異なるタスク間で排他制御を行いたい時に使用するが、マルチタスク環境ではプロセスの多重起動を防止する用途にも使える。

ミューテックスの起源はディジタル・イクイップメント・コーポレーションにおける、機材の使用管理が由来である。使用可能な機材の上には小さな旗が置かれ、その旗を手にいれた者がその機材の使用権利を獲得する。この排他制御からヒントを得たVMS開発チームはVMSの排他制御にミューテックスを実現した。そしてその技術はデヴィッド・カトラーを筆頭としたVMS開発チームと共にMicrosoft Windows NTにも移された。

POSIXスレッド  のミューテックスは、VMSやWin32と違い、自らP操作したミューテックスをさらにP操作するとデッドロックを起こす。そのため若干取り扱いは不便である。再帰ロックを許可する場合は、ミューテックスの初期化時にPTHREAD_MUTEX_RECURSIVEを設定した属性を使用する必要がある。

ミューテックスを実現する方法は様々あり、大きくハードウェアによる方式とソフトウェアによる方式に分けられる。ソフトウェアによる方式にも、様々なアルゴリズムが提案されている。詳しくは、排他制御の実施を参照。

2. ミューテックスの使用
-------------

ミューテックス機構を使用するには、プログラムでミューテックスオブジェクトを作成する必要がある。ミューテックスオブジェクトはシグナルおよび非シグナルの二つの状態を持ち、それぞれミューテックスオブジェクトが所有可能および所有不可能である事を表す。

2.1. クリティカルセクションへの進入
--------------------

クリティカルセクションに入るにはミューテックスオブジェクトの所有を行う。所有というのはインスタンスの作成という意味ではなく、クリティカルセクションへの進入権を得るという事である。この時、ミューテックスオブジェクトの状態によってクリティカルセクションに入れるかどうかが異なる。

シグナル状態すぐにクリティカルセクションに入る事ができ、処理を続行できる。この時、ミューテックスオブジェクトはシグナル状態から非シグナル状態になり、これによって後続のタスクが同時にクリティカルセクションに入る事を防ぐ。
非シグナル状態クリティカルセクションに入る事はできず、通常はシグナル状態になるまでタスクは待機状態になる。実装によってはタイムアウトを指定する事ができ、指定した期間内にミューテックスオブジェクトが解放されなければ所有は失敗し、タスクに処理が戻る。この時、タスクは所有が失敗した事を感知し、処理を中断するべきである。

2.2. クリティカルセクションからの離脱
---------------------

クリティカルセクションから抜ける時はミューテックスオブジェクトを解放する。解放されたミューテックスオブジェクトは非シグナル状態からシグナル状態に戻り、これによって後続のタスクはミューテックスオブジェクトを所有する事が可能になる。

3. 環境ごとの使用法
-----------

3.1. POSIX
----------

3.1.1. プロセス間の場合
---------------

Pthreadsのミューテックスオブジェクトを初期化する際に使用する属性pthread_mutexattr_tに対して、pthread_mutexattr_setpshared関数にてPTHREAD_PROCESS_SHAREDを指定する。ただしサポートされない環境もある。

3.1.2. プロセス内の場合
---------------

Pthreadsのミューテックスオブジェクトpthread_mutex_tを使う。

3.2. Windows
------------

3.2.1. プロセス間の場合
---------------

プロセス間の排他制御には、以下の方法がある。

Mutex - ミューテックスオブジェクトを使う。初期化にはCreateMutexWin32 API関数を使う。
Metered Section - Critical Sectionの拡張であり、CreateMeteredSection関数の実装例がMSDNに記載されている。Mutexより高速であるとされている。[1]date=2017年5月}}[2]

3.2.2. プロセス内の場合
---------------

プロセス間でミューテックスを共有する必要がない場合は、以下の方法がある。

Critical Section - クリティカルセクションオブジェクトを使う。初期化にはInitializeCriticalSectionWin32 API関数を使う。Mutexより高速である。
Mutex - 無名のミューテックスオブジェクトを使う。MFCにはC++のコンストラクタ/デストラクタによるRAII機構を利用した、Win32同期オブジェクトのラッパークラスCMutexやCCriticalSectionが用意されている。

3.3. C++
--------

PthreadsやWin32 APIを直接使用するか、あるいは以下に述べるようなポータブルなライブラリを使用する。

3.3.1. プロセス間の場合
---------------

Boost C++ライブラリのboost::interprocess::interprocess_mutexなどを使う。内部的には共有メモリやメモリマップトファイルを使って実装されることもある。Windows実装の場合はWin32ミューテックスを使う実験的コードも存在する。

3.3.2. プロセス内の場合
---------------

Boost C++ライブラリのboost::mutexや、C++11以降で標準化されたstd::mutexを使う。再帰ロックを許可する場合は、boost::recursive_mutexやstd::recursive_mutexを使う。通常はlock_guardやunique_lockといったロック管理クラスと組み合わせて使用することが多い。

3.4. .NET
---------

3.4.1. プロセス間の場合
---------------

System.Threading.Mutexクラスを使う。

3.4.2. プロセス内の場合
---------------

System.Threading.Monitorクラスが用意されているが、このクラスを使用した言語組み込みの同期機能も用意されている。例えばC#では lock ステートメント、Visual Basic .NETでは SyncLock ステートメントで、クリティカルセクションを任意のロックオブジェクトにより相互排他ロックすることが可能である。ただし、thisオブジェクトやSystem.Typeインスタンスなど、ロックに使用してはいけないとされているオブジェクトもある。また、メソッド全体を包含する場合は、[MethodImplAttribute]属性を適用することができる。ただしC# 5.0/VB.NET 11で追加されたawait/Await演算子を含むコードブロックをlock/SyncLockでロックすることはできず、System.Threading.SemaphoreSlimクラスなどを使用する必要がある。

C++/CLI向けにはRAIIを応用したmsclr::lockクラスが用意されている。

3.5. Java
---------

Javaにはミューテックスクラスが存在せず、パーミッション数1で初期化したname=java.util.concurrent.Semaphoreクラスで代用する。また、スレッドの同期機構が言語仕様に組み込んであり、synchronizedブロックにて任意のオブジェクトをロックオブジェクトとして使用できる。synchronizedメソッドではthisオブジェクトもしくはname=java.lang.Classがロックに使われる。プロセス間で使用可能なミューテックスは直接サポートされておらず、ファイルロック  を利用する必要がある。

3.6. μITRON仕様
-------------

3.0仕様以前には、ミューテックスは存在しない。広義のミューテックスはセマフォで代用することは可能であるが、優先度逆転を防げない。 しかしながら、3.0仕様準拠OSでも、実装独自に優先度逆転を防止できるミューテックスが存在する可能性はある。

4.0仕様以降では、優先度上限および優先度継承をサポートするミューテックスオブジェクトが追加された。しかし、スタンダードプロファイルには含まれておらず、実質オプション扱いである。

4. 脚注
-----

5. 関連項目
-------

排他制御
並行計算
クリティカルセクション
セマフォ
デッドロック
スレッド 
プロセス
マルチタスク

pl:Mutex