kazmax - Linux で自宅サーバー

pthread_mutex_init - ライブラリコールの説明 - Linux コマンド集 一覧表

  1. 名前
  2. 書式
  3. 説明
  4. 取り消し
  5. 非同期シグナルに対する安全性
  6. 返り値
  7. エラー
  8. 著者
  9. 関連項目

名前

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 用 ) を用いて 静的に初期化することもできる。