pthread_mutex_init - ライブラリコールの説明 - Linux コマンド集 一覧表
名前
pthread_mutex_init, pthread_mutex_lock, pthread_mutex_trylock,
pthread_mutex_unlock, pthread_mutex_destroy - mutex の操作
書式
#include <pthread.h>
pthread_mutex_t
fastmutex
= PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t
recmutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_t
errchkmutex
= PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
int pthread_mutex_init(pthread_mutex_t *
mutex
, const pthread_mutexattr_t *
mutexattr
);
int pthread_mutex_lock(pthread_mutex_t *
mutex
));
int pthread_mutex_trylock(pthread_mutex_t *
mutex
);
int pthread_mutex_unlock(pthread_mutex_t *
mutex
);
int pthread_mutex_destroy(pthread_mutex_t *
mutex
);
説明
mutex は、排他制御 (MUTual EXclusion) の仕組みであり、共有データの同時更新
からの保護、クリティカルセクション (critical section) や
モニタの実装などに使われる。
mutex は二つの状態を取りうる。それは、アンロック状態(どのスレッドにも
保有されていない)とロック状態(一つのスレッドに保有されている)である。
二つの異なるスレッドが同時に一つの mutex を保有することはない。既に他の
スレッドによってロックされた mutex をロックしようとするスレッドは、保有
側のスレッドが先にその mutex をアンロックするまで実行を停止させられる。
"pthread_mutex_init"
は
"mutex"
が指す mutex オブジェクトを、
mutexattr
で指定された mutex 属性オブジェクトに従って初期化する。
"mutexattr"
が
NULL
,ならば、デフォルトの属性がこのかわりに使われる。
LinuxThreads の実装はただ一つの属性
mutex kind
だけに対応している。この属性は、「速い」(``fast'')、
「再帰的な」(``recursive'')、または
「エラー検査を行なう」(``error checking'')のいずれかを
指定するものである。
mutex の種別(kind)は、その mutex を既に保有しているスレッドが、
それを再びロックできるかどうかを決定する。
デフォルトの種別は「速い」である。mutex 属性のより詳しい情報は、
pthread_mutexattr_init
(3) を見よ。
"pthread_mutex_t"
型の変数は、(速い mutex に対する)定数
"PTHREAD_MUTEX_INITIALIZER"
と、(再帰的 mutex に対する)
"PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP"
および、(エラー検査を行なう mutex に対する)
"PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP"
で、静的に初期化することもできる。
"pthread_mutex_lock"
は、与えられた mutex をロックする。mutex が現在ロックされていなければ、
それはロックされ、呼び出しスレッドによって所有される。この場合
"pthread_mutex_lock"
は直ちに返る。mutex が他のスレッドによって既にロックされていたのならば、
"pthread_mutex_lock"
は mutex がアンロックされるまで呼び出しスレッドの実行を停止させる。
mutex が呼び出し側のスレッドにより既にロックされている場合には、
"pthread_mutex_lock"
の振舞いは、mutex の種別に依存する。mutex の種別が「速い」であれば、
呼び出しスレッドは mutex がアンロックされるまで実行を停止する。
従って事実上呼び出しスレッドのデッドロックを引き起こす。
mutex の種別が「エラーをチェックする」であれば、
"pthread_mutex_lock"
はエラーコード
EDEADLK
とともに直ちに戻る。mutex の種別が「再帰的」ならば、
"pthread_mutex_lock"
は成功し直ちに戻る。この際、呼び出しスレッドが、その mutex を
ロックした回数を記録する。この mutex がアンロック状態に戻るには、
同数の
"pthread_mutex_unlock"
操作が実行されねばならない。
"pthread_mutex_trylock"
は
pthread_mutex_lock
と同様に振舞うが、mutex が既に他のスレッドによって
(あるいは、「速い」 mutex の場合、呼び出しスレッドによって)
ロックされている場合、呼び出しスレッドをブロックしない。
かわりに、
"pthread_mutex_trylock"
はエラーコード
EBUSY
で直ちに戻る。
"pthread_mutex_unlock"
は、与えられた mutex をアンロックする。
pthread_mutex_unlock
の開始時点で、この mutex は呼び出しスレッドによりロックされ
所有されているものと仮定される。
mutex が「速い」種別のものならば、
"pthread_mutex_unlock"
は常にそれをアンロック状態に戻す。それが「再帰的な」種別ならば、
mutex のロック計数(この mutex に対して
"pthread_mutex_lock"
操作が呼び出しスレッドで実行された回数)
を一つ減らし、この計数がゼロになった時に、初めて mutex が
実際にアンロックされる。
「エラーを検査する」mutex に対しては、
"pthread_mutex_unlock"
は実行時に実際に、mutex が開始時点でロックされているか、
また、それは現在
pthread_mutex_unlock
を呼んでいるのと同じスレッドによってロックされたかどうか、を検査する。
これらの条件が満たされない場合には、エラーコードが返され、mutex は
不変のままにされる。「速い」mutex と「再帰的な」mutex はこのような
チェックを行なわなず、よって、ロックされた mutex を所有者以外の
スレッドによってアンロックすることを可能にしている。これは、移植性の
ない振舞いであり、これに依存するようなことはすべきでない。
"pthread_mutex_destroy"
は、mutex オブジェクトを破壊し、それが保持している可能性のある
資源を開放する。mutex は関数の開始時点でアンロックされていなければ
ならない。LinuxThreads の実装では、いかなる資源も mutex オブジェクトに
付随していない。故に
"pthread_mutex_destroy"
は実際のところ、mutex がアンロックされているかどうかを検査する
以外のことは何もしない。
取り消し
いかなる mutex 関数も取り消しポイントではない。
pthread_mutex_lock
でさえも、それが任意の時間スレッドの実行を停止させうるという
事実にも関わらず、取り消しポイントではない。これにより、取り消し
ポイントにおける mutex の状態は予測可能となり、取り消しハンドラが、
スレッドの実行停止以前にアンロックされる必要のある mutex まさにそれ
のみを、正確にアンロックすることを可能にしている。この結果、遅延
取り消しを用いるスレッドは、決して余計な時間 mutex を所有することはない。
非同期シグナルに対する安全性
mutex 関数は非同期シグナルに対して安全ではない。これの
意味するところは、それらはシグナルハンドラから呼ぶべきではない、
ということである。特に
"pthread_mutex_lock"
または
"pthread_mutex_unlock"
のシグナルハンドラからの呼び出しは、呼び出しスレッドをデッド
ロックさせる恐れがある。
返り値
"pthread_mutex_init"
は、常に 0 を返す。他の mutex 関数は、成功すれば 0 を返し、
エラーでは非ゼロのエラーコードを返す。
エラー
"pthread_mutex_lock"
はエラーの際、次のエラーコードを返す:
- "EINVAL"
-
mutex が適切に初期化されていない。
- "EDEADLK"
-
mutex は既に呼び出しスレッドによりロックされている。
(「エラー検査を行なう」 mutexes のみ)
"pthread_mutex_trylock" はエラーの際、次のエラーコードを返す:
- "EBUSY"
-
現在ロックされているので mutex を取得できない。
- "EINVAL"
-
mutex が適切に初期化されていない。
O"pthread_mutex_unlock" はエラーの際、次のエラーコードを返す:
- "EINVAL"
-
mutex が適切に初期化されていない。
- "EPERM"
-
呼び出しスレッドは mutex を所有していない。(「エラーを検査する」 mutex のみ)
"pthread_mutex_destroy" はエラーの際、次のエラーコードを返す:
- "EBUSY"
-
mutex は現在ロックされている。
著者
Xavier Leroy <Xavier.Leroy@inria.fr>
関連項目
pthread_mutexattr_init
(3),
pthread_mutexattr_setkind_np
(3),
pthread_cancel
(3).
例
共有される大域変数
"x"
は mutex により次のように保護される:
int x; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
全ての "x" へのアクセスとその変更は "pthread_mutex_lock" と "pthread_mutex_unlock" によって、次のように囲まれていなければならない:
pthread_mutex_lock(&mut); /* x の操作 */ pthread_mutex_unlock(&mut);
[訳注] glibc-linuxthreads の最新のドキュメントは Texinfo 形式で提供されている。
上の記述は glibc-linuxthreads-2.2 以降では正しくない。
以下は glibc-linuxthreads-2.3.1 の Texinfo ファイルからの引用である。
種別 (kind) が型 (type) に変更されている。
LinuxThreads 実装はただ 1 つの mutex 属性に対応している。
それは mutex 型 (mutex type) で、
「速い (fast) 」、「再帰的な (recursive) 」、
「時刻情報つき (timed) 」、「エラー検査を行なう (error checking) 」の
いずれかである。
mutex 型は、
あるスレッドが自分自身ですでに保持している mutex をロックできるかどうかを
決定する。
デフォルトの mutex 型は「時刻情報つき (timed) 」である。
pthread_mutex_t
型の変数は、定数
"PTHREAD_MUTEX_INITIALIZER"
( 時刻情報つき (timed) mutex 用 ) 、
"PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP"
( 再帰的な (recursive) mutex 用 ) 、
"PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP"
( 速い (fast) mutex 用 ) 、
"PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP"
( エラー検査を行なう (error checking) mutex 用 ) を用いて
静的に初期化することもできる。