マルチスレッドのプログラミング

相互排他ロック属性

相互排他ロック (mutex ロック) は、スレッドの実行を直列化したいときに使用します。相互排他ロックでスレッド間の同期をとるときは、通常はコードの危険領域が複数のスレッドによって同時に実行されないようにするという方法が用いられます。単一のスレッドのコードを保護する目的で相互排他ロックを使用することもできます。

デフォルトの mutex 属性を変更するには、属性オブジェクトを宣言して初期化します。多くの場合、アプリケーションの先頭部分の一箇所で設定しますので、mutex 属性は、すばやく見つけて簡単に変更できます。次の表に、この節で説明する mutex 属性操作関数を示します。

表 4-1 mutex 属性ルーチン

「mutex 属性オブジェクトの初期化」

「pthread_mutexattr_init(3T)」

「mutex 属性オブジェクトの削除」

「pthread_mutexattr_destroy(3T)」

「mutex の適用範囲設定 」

「pthread_mutexattr_setpshared(3T)」

「mutex のスコープの値の取得 」

「pthread_mutexattr_getpshared(3T)」

「mutex の 型属性の設定」

「pthread_mutexattr_settype(3T)」

「mutex の 型属性の取得」

「pthread_mutexattr_gettype(3T)」

mutex のスコープ定義について、Solaris と POSIX との相違点を表 4-2 に示します。

表 4-2 mutex の適用範囲の比較

Solaris 

POSIX 

定義 

USYNC_PROCESS

PTHREAD_PROCESS_SHARED

このプロセスと他のプロセスのスレッドの間で同期をとるために使用する 

USYNC_PROCESS_ROBUST

相当する定義なし

異なるプロセスのスレッド間で安定的に同期をとるために使用する

USYNC_THREAD

PTHREAD_PROCESS_PRIVATE

このプロセスのスレッドの間でだけ同期をとるために使用する 

mutex 属性オブジェクトの初期化

pthread_mutexattr_init(3T)

pthread_mutexattr_init(3T) は、このオブジェクトに関連付けられた属性をデフォルト値に初期化します。各属性オブジェクトのための記憶領域は、実行時にスレッドによって割り当てられます。

この関数が呼び出されたときの pshared 属性のデフォルト値は PTHREAD_PROCESS_PRIVATE で、初期化された mutex を 1 つのプロセスの中だけで使用できるという意味です。

プロトタイプ:
int	pthread_mutexattr_init(pthread_mutexattr_t *mattr);
#include <pthread.h>


pthread_mutexattr_t mattr;
int ret;

/* 属性をデフォルト値に初期化する */
ret = pthread_mutexattr_init(&mattr); 

mattr は不透明な型で、システムによって割り当てられた属性オブジェクトを含んでいます。mattr のスコープとして取りうる値は、PTHREAD_PROCESS_PRIVATE (デフォルト) と PTHREAD_PROCESS_SHARED です。

mutex 属性オブジェクトを再使用するには、pthread_mutexattr_destroy(3T) への呼び出しによって事前に削除しなければなりません。pthread_mutexattr_init() を呼び出すと、不透明なオブジェクトが割り当てられます。そのオブジェクトが削除されないと、結果的にメモリーリークを引き起こします。

戻り値

正常終了時は 0 です。それ以外の戻り値は、エラーが発生したことを示します。以下のいずれかの条件が検出されると、この関数は失敗し、次の値を戻します。


ENOMEM

メモリーが足りなくて、mutex 属性オブジェクトを初期化できません。

mutex 属性オブジェクトの削除

pthread_mutexattr_destroy(3T)

pthread_mutexattr_destroy(3T) は、pthread_mutexattr_init() によって生成された属性オブジェクトの管理に使用されていた記憶領域の割り当てを解除します。

プロトタイプ:
int	pthread_mutexattr_destroy(pthread_mutexattr_t *mattr)
#include <pthread.h>

pthread_mutexattr_t mattr;
int ret;

/* 属性を削除する */
ret = pthread_mutexattr_destroy(&mattr); 

戻り値

正常終了時は 0 です。それ以外の戻り値は、エラーが発生したことを示します。以下の条件が検出されると、この関数は失敗し、対応する値を戻します。


EINVAL

mattr で指定された値が無効です。

mutex の適用範囲設定

pthread_mutexattr_setpshared(3T)

pthread_mutexattr_setpshared(3T) は、mutex 変数の適用範囲を設定します。

mutex 変数の値は、プロセス専用 (プロセス内) とシステム共通 (プロセス間) のどちらかです。pshared 属性を PTHREAD_PROCESS_SHARED 状態に設定して mutex を生成し、その mutex が共有メモリー内に存在する場合、その mutex は複数のプロセスのスレッドの間で共有できます。これは Solaris スレッドにおいて mutex_init()USYNC_PROCESS フラグを使用するのに相当します。

プロトタイプ:
int	pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr,
    int pshared);
#include <pthread.h>

pthread_mutexattr_t mattr;
int ret;

ret = pthread_mutexattr_init(&mattr);
/*
 * デフォルト値にリセットする: private
 */
ret = pthread_mutexattr_setpshared(&mattr,
     PTHREAD_PROCESS_PRIVATE);

mutex の pshared 属性を PTHREAD_PROCESS_PRIVATE に設定した場合、その mutex を操作できるのは同じプロセスで生成されたスレッドだけです。

戻り値

正常終了時は 0 です。それ以外の戻り値は、エラーが発生したことを示します。以下の条件が検出されると、この関数は失敗し、対応する値を戻します。


EINVAL

mattr で指定された値が無効です。

mutex のスコープの値の取得

pthread_mutexattr_getpshared(3T)

pthread_mutexattr_getpshared(3T) は、pthread_mutexattr_setpshared() によって定義された、mutex 変数の適用範囲を返します。

プロトタイプ:
int	pthread_mutexattr_getpshared(pthread_mutexattr_t *mattr,
    int *pshared);
#include <pthread.h>

pthread_mutexattr_t mattr;
int pshared, ret;

/* mutex の pshared を取得する */
ret = pthread_mutexattr_getpshared(&mattr, &pshared); 

属性オブジェクト mattrpshared の現在値を取得します。これは PTHREAD_PROCESS_SHAREDPTHREAD_PROCESS_PRIVATE のどちらかです。

戻り値

正常終了時は 0 です。それ以外の戻り値は、エラーが発生したことを示します。以下の条件が検出されると、この関数は失敗し、対応する値を戻します。


EINVAL

mattr で指定された値が無効です。

mutex の 型属性の設定

pthread_mutexattr_settype(3T)

#include <pthread.h>

int pthread_mutexattr_settype(pthread_mutexattr_t  *attr , int type);

pthread_mutexattr_settype(3T) は、 mutex の 型 (type) 属性を設定します。型 属性のデフォルト値は PTHREAD_MUTEX_DEFAULT です。

型 (type) 引数は mutex の型を指定します。有効な mutex 型を以下に示します。


PTHREAD_MUTEX_NORMAL

この型の mutex はデッドロックを検出しません。スレッドが、この mutex をロック解除しないでもう一度ロックしようとすると、スレッドはデッドロックします。別のスレッドによってロックされた mutex をロック解除しようとした場合、引き起こされる動作は未定義です。また、ロック解除された mutex をロック解除しようとした場合、引き起こされる動作は不定です。


PTHREAD_MUTEX_ERRORCHECK

この型の mutex はエラーチェックを行います。スレッドがこの mutex をロック解除しないでもう一度ロックしようとすると、エラーを返します。別のスレッドがロックした mutex をロック解除しようとすると、エラーを返します。また、ロック解除された mutex をロック解除しようとするとエラーを返します。


PTHREAD_MUTEX_RECURSIVE

スレッドがこの mutex をロック解除しないでもう一度ロックしようとすると、正常にロックできます。PTHREAD_MUTEX_NORMAL 型の mutex ではロックを繰り返すとデッドロックが発生しますが、この型の mutex では発生しません。複数回ロックされた mutex を別のスレッドが獲得するときには、その前に同じ回数ロック解除する必要があります。あるスレッドがロックした mutex を別のスレッドがロック解除しようとすると、エラーが返されます。ロック解除されている mutex をスレッドがロック解除しようとすると、エラーが返されます。 mutex の型は、プロセス共有属性が PTHREAD_PROCESS_PRIVATE の mutex に対してだけサポートされます。


PTHREAD_MUTEX_DEFAULT

このタイプの mutex を繰り返しロックしようとした場合、引き起こされる動作は未定義です。この型の mutex を、ロックしていないスレッドがロック解除しようとした場合、引き起こされる動作は未定義です。この型の、ロックされていない mutex をロック解除しようとした場合、引き起こされる動作は未定義です。この型の mutex は、他の mutex 型に割り当てることができます。Solaris スレッドでは、PTHREAD_PROCESS_DEFAULTPTHREAD_PROCESS_NORMAL に割り当てられます。

戻り値

pthread_mutexattr_settype 関数は、正常に終了すると 0 を返します。それ以外の場合は、エラーを示す値を返します。


EINVAL

type の値が無効です。


EINVAL

attr で指定された値が無効です。

mutex の 型属性の取得

pthread_mutexattr_gettype(3T)

#include <pthread.h>

int pthread_mutexattr_gettype(pthread_mutexattr_t  *attr , int  *type);

pthread_mutexattr_gettype(3T) は、pthread_mutexattr_settype() によって設定された、 mutex の 型 (type) 属性を取得します。型属性のデフォルト値は PTHREAD_MUTEX_DEFAULT です。

型 (type) 引数は mutex の型を指定します。有効な mutex 型を以下に示します。

各型の説明については、「pthread_mutexattr_settype(3T)」を参照してください。