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

バリアー同期の使用

タスク全体を続行させるために複数のタスクの完了を待つ必要がある場合は、バリアー同期を使用できます。POSIX スレッドでは、バリアー関数とともに、バリアーと呼ばれる同期オブジェクトを指定します。これらの関数は、バリアー上で同期させるスレッドの数を指定してバリアーを作成し、各スレッドを、タスクの実行後、すべてのスレッドがバリアーに到達するまでバリアーで待機するように設定します。最後のスレッドがバリアーに到達すると、すべてのスレッドが実行を再開します。

バリアー同期の詳細については、「共有メモリー型の並列コンピュータでのループの並列化」を参照してください。

同期バリアーの初期化

バリアーにリソースを割り当て、その属性を初期化するには、pthread_barrier_init(3C) を使用します。

pthread_barrier_init() の構文

int pthread_barrier_init(pthread_barrier_t  *barrier, 
          const pthread_barrierattr_t *restrict attr, 
          unsigned count);
#include <pthread.h> 
pthread_barrier_t barrier; 
pthread_barrierattr_t attr;
unsigned count;
int ret; 
ret = pthread_barrier_init(&barrier, &attr, count);

pthread_barrier_init() 関数は、barrier が参照するバリアーを使用するために必要なすべてのリソースを割り当て、attr が参照する属性でバリアーを初期化します。attr が NULL の場合は、デフォルトのバリアー属性が使用されます。この場合の結果は、デフォルトのバリアー属性オブジェクトのアドレスを渡す場合と同じです。count 引数には、pthread_barrier_wait() を呼び出す必要のあるスレッドの数を指定します。それまでは、どのスレッドも呼び出しから正常に復帰できません。count で指定する値は 1 以上にする必要があります。

pthread_barrier_init() の戻り値

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


EINVAL

説明:

count で指定された値が 0 に等しいか、または attr で指定された値が無効です。


EAGAIN

説明:

別のバリアーを初期化するために必要なシステムリソースが不足しています。


ENOMEM

説明:

メモリー不足のためバリアーを初期化できません。


EBUSY

説明:

バリアーが別のスレッドによって使用されている間 (たとえば、pthread_barrier_wait() の呼び出しで使用されている間) にそのバリアーの削除の試行が検出されました。

バリアーで同期をとるためのスレッドの待機

指定したバリアーでスレッドの同期をとるには、pthread_barrier_wait(3C) を使用します。呼び出しスレッドは、必要な数のスレッドがこのバリアーを指定して pthread_barrier_wait() を呼び出すまでブロックされます。スレッドの数は、pthread_barrier_init() 関数で指定されます。

必要な数のスレッドがこのバリアーを指定して pthread_barrier_wait() を呼び出すと、1 つの不定のスレッドに定数 PTHREAD_BARRIER_SERIAL_THREAD が返され、残りの各スレッドには 0 が返されます。バリアーは次に、このバリアーを参照していた最新の pthread_barrier_init() 関数の結果として保持していた状態にリセットされます。

pthread_barrier_wait() の構文

int pthread_barrier_wait(pthread_barrier_t  *barrier);
#include <pthread.h> 
pthread_barrier_t barrier; 
int ret; 
ret = pthread_barrier_wait(&barrier);

pthread_barrier_wait() の戻り値

pthread_barrier_wait() 関数は、正常終了時に PTHREAD_BARRIER_SERIAL_THREAD を返します。この値は pthread.h で定義されており、このバリアーで同期がとられた 1 つの任意のスレッドに返されます。ほかの各スレッドには、0 が返されます。それ以外の場合は、エラーコードが返されます。


EINVAL

説明:

barrier で指定された値が、初期化されたバリアーオブジェクトを表していません。

同期バリアーの削除

バリアーが必要なくなったら、そのバリアーを削除するようにすべきです。barrier が参照するバリアーを削除し、そのバリアーによって使用されているリソースをすべて解放するには、pthread_barrier_destroy(3C) を使用します。

pthread_barrier_destroy の構文

int pthread_barrier_destroy(pthread_barrier_t *barrier);
#include <pthread.h> 
pthread_barrier_t barrier; 
int ret; 
ret = pthread_barrier_destroy(&barrier);

pthread_barrier_destroy の戻り値

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


EINVAL

説明:

barrier の値が無効です。


EBUSY

説明:

バリアーが別のスレッドによって使用されている間 (たとえば、pthread_barrier_wait() で使用されている間) にそのバリアーの削除の試行が検出されました。

バリアー属性オブジェクトの初期化

pthread_barrierattr_init(3C) 関数は、バリアー属性オブジェクト attr を、実装によってこのオブジェクト用に定義された属性のデフォルト値に初期化します。現在、プロセス共有の属性のみが提供されており、この属性を取得および設定するために pthread_barrierattr_getpshared() および pthread_barrierattr_setpshared() 関数が使用されます。

バリアー属性オブジェクトを使用して 1 つ以上のバリアーを初期化したあと、この属性オブジェクトに影響するどの関数 (削除を含む) を使用しても、前に初期化されたバリアーには影響しません。

pthread_barrierattr_init() の構文

int pthread_barrierattr_init(pthread_barrierattr_t *attr);
#include <pthread.h> 
pthread_barrierattr_t attr; 
int ret; 
ret = pthread_barrierattr_init(&attr);

pthread_barrierattr_init() の戻り値

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


ENOMEM

説明:

バリアー属性オブジェクトを初期化するためのメモリーが足りません。

バリアーのプロセス共有の属性の設定

pthread_barrierattr_setpshared() 関数は、attr が参照する初期化された属性オブジェクト内のプロセス共有の属性を設定します。プロセス共有の属性は、次のいずれかの値を持ちます。

PTHREAD_PROCESS_PRIVATE

バリアーを操作できるのは、そのバリアーを初期化したスレッドと同じプロセス内で作成されたスレッドだけです。これはプロセス共有の属性のデフォルト値です。

PTHREAD_PROCESS_SHARED

バリアーが割り当てられているメモリーにアクセスできる任意のスレッドがバリアーを操作できます。

pthread_barrierattr_setpshared() の構文

int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared);

pthread_barrierattr_setpshared() の戻り値

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


EINVAL

説明:

attr の値が無効か、または pshared に指定された新しい値が無効です。

バリアーのプロセス共有の属性の取得

pthread_barrierattr_getpshared(3C) 関数は、attr が参照する属性オブジェクトからプロセス共有の属性の値を取得します。この値は、pthread_barrierattr_setpshared() 関数で設定されます。

pthread_barrierattr_getpshared() の構文

int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict attr, 
          int *restrict pshared);

pthread_barrierattr_getpshared() の戻り値

pthread_barrierattr_getpshared() は、正常終了時に 0 を返し、attr のプロセス共有の属性の値を pshared パラメータが参照するオブジェクトに格納します。それ以外の戻り値は、エラーが発生したことを示します。以下の条件が検出されると、この関数は失敗し、対応する値を返します。


EINVAL

説明:

attr の値が無効です。

バリアー属性オブジェクトの削除

pthread_barrierattr_destroy() 関数は、バリアー属性オブジェクトを削除します。削除された attr 属性オブジェクトは、pthread_barrierattr_init() を使用して再初期化することができます。

バリアー属性オブジェクトを使用して 1 つ以上のバリアーを初期化したあと、このオブジェクトを削除しても、前に初期化されたバリアーには影響しません。

pthread_barrierattr_destroy() の構文

#include <pthread.h>

int  pthread_barrierattr_destroy(pthread_barrierattr_t *attr);

pthread_barrierattr_destroy() の戻り値

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


EINVAL

説明:

attr の値が無効です。