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

条件変数の属性

条件変数は、ある条件が真になるまでスレッドを原子的操作によりブロックしたいときに使用します。必ず相互排他ロックとともに使用してください。

条件変数を使うと、特定の条件が真になるまでスレッドを原子的操作によりブロックできます。この条件判定は、相互排他ロックにより保護された状態で行います。

条件が偽のとき、スレッドは通常は条件変数でブロック状態に入り、相互排他ロックを原子的操作により解除して、条件が変更されるのを待ちます。別のスレッドが条件を変更すると、そのスレッドはそれに関連する条件変数にシグナルを送り、その条件変数でブロックしているスレッドを呼び起こします。呼び起こされたスレッドは再度相互排他ロックを獲得し、条件を再び評価します。

異なるプロセスに所属するスレッドの間で、条件変数を使って同期をとるためには、連携するそれらのプロセスの間で共有される書き込み可能なメモリーに、条件変数の領域を確保する必要があります。

スケジューリング方針は、ブロックされたスレッドがどのように呼び起こさるかを決定します。デフォルト SCHED_OTHER の場合、スレッドは優先順位に従って呼び起こされます。

条件変数の属性は、使用する前に設定して初期化しておかなければなりません。条件変数の属性を操作する関数を表 4-4 に示します。

表 4-4 条件変数の属性

「条件変数の属性の初期化」

「pthread_condattr_init(3T)」

「条件変数の属性の削除」

「pthread_condattr_destroy(3T)」

「条件変数のスコープの設定」

「pthread_condattr_setpshared(3T)」

「条件変数のスコープの取得」

「pthread_condattr_getpshared(3T)」

条件変数のスコープ定義について、オリジナルの Solaris スレッドとの相違点を表 4-5 に示します。

表 4-5 条件変数のスコープの比較

Solaris 

POSIX 

定義 

USYNC_PROCESS

PTHREAD_PROCESS_SHARED

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

USYNC_THREAD

PTHREAD_PROCESS_PRIVATE

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

条件変数の属性の初期化

pthread_condattr_init(3T)

pthread_condattr_init() は、このオブジェクトに関連付けられた属性をデフォルト値に初期化します。各属性オブジェクトのための記憶領域は、実行時にスレッドシステムによって割り当てられます。この関数が呼び出されたときの pshared 属性のデフォルト値は PTHREAD_PROCESS_PRIVATE で、初期化された条件変数を 1 つのプロセスの中だけで使用できるという意味です。

プロトタイプ:
int	pthread_condattr_init(pthread_condattr_t *cattr);
#include pthread.h
pthread_condattr_t  cattr;
int ret;

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

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

条件変数属性を再使用するには、pthread_condattr_destroy(3T) によって事前に削除しなければなりません。pthread_condattr_init() 呼び出しは、不透明なオブジェクトへのポインタを戻します。そのオブジェクトが削除されないと、結果的にメモリーリークを引き起こします。

戻り値

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


ENOMEM

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


EINVAL

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

条件変数の属性の削除

pthread_condattr_destroy(3T)

このルーチンは記憶領域を解除し、属性オブジェクトを無効にします。

プロトタイプ:
int	pthread_condattr_destroy(pthread_condattr_t *cattr);
#include <pthread.h>
pthread_condattr_t cattr;
int ret;

/* 属性を削除する */
ret
 = pthread_condattr_destroy(&cattr); 

戻り値

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


EINVAL

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

条件変数のスコープの設定

pthread_condattr_setpshared(3T)

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

mutex の pshared 属性を PTHREAD_PROCESS_PRIVATE (デフォルト値) に設定した場合、その mutex を操作できるのは同じプロセスで生成されたスレッドに限られます。PTHREAD_PROCESS_PRIVATE を使用した場合、その動作はオリジナルの Solaris スレッドにおいて cond_init() 呼び出しで USYNC_THREAD フラグを使用したとき、すなわち局所条件変数と同じになります。PTHREAD_PROCESS_SHARED は広域条件変数に相当します。

プロトタイプ:
int	pthread_condattr_setpshared(pthread_condattr_t *cattr,
    int pshared);
#include <pthread.h>

pthread_condattr_t cattr;
int ret;

/* 全プロセス */
ret = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);

/* 1 つのプロセス内 */
ret = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE);

戻り値

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


EINVAL

cattr または pshared の値が無効です。

条件変数のスコープの取得

pthread_condattr_getpshared(3T)

pthread_condattr_getpshared() は属性オブジェクト cattrpshared の現在のスコープ値を取得します。これは PTHREAD_PROCESS_SHAREDPTHREAD_PROCESS_PRIVATE のどちらかです。

プロトタイプ:
int	pthread_condattr_getpshared(const pthread_condattr_t *cattr,
    int *pshared);
#include <pthread.h>

pthread_condattr_t cattr;
int pshared;
int ret;

/* 条件変数の pshared 値を取得する */
ret = pthread_condattr_getpshared(&cattr, &pshared); 

戻り値

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


EINVAL

cattr の値が無効です。