pthread mutex
- pthread mutexには、「fast(速い)」、「recursive(再帰的な)」、「error checking(エラー検査を行なう)」の三つの属性がある。
- pthread_mutex_initにてmutexattrを指定しない限り、デフォルトでは「fast(速い)」属性のミューテックスとなる。
- pthread_mutex_tを静的に初期化する場合は、PTHREAD_MUTEX_INITIALIZERを使用する。
- この場合、「fast(速い)」ミューテックスとして初期化される。
- 「recursive(再帰的な)」ミューテックスとして初期化したい場合はPTHREAD_RECURSIVE_MUTEX_INITIALIZER_NPを使用する。
- 「error checking(エラー検査を行なう)」ミューテックスとして初期化したい場合はPTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NPを使用する。
- ミューテックスに入るときはpthread_mutex_lock、出るときはpthread_mutex_unlockを用いる。
- pthread_mutex_lockの代わりにpthread_mutex_trylockをコールすると、ミューテックスがロックされている場合(他のスレッドがミューテックスに入っている場合)は、待機せず即座に呼び元に処理が戻る(このときエラーコードEBUSYを返す)。
- プロセス間での同期を行う場合にはセマフォを使う
使用例
// gcc -pthread -std=c99
#include <stdio.h>
#include <pthread.h>
#include <time.h>
// ミューテックスオブジェクト
pthread_mutex_t mutex;
// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#define THREAD_COUNT (10)
// ワーカースレッドのオブジェクト格納用の配列
pthread_t threads[THREAD_COUNT];
// ワーカースレッドからアクセスされる変数
int global_value;
//
// ミリ秒単位のsleep
//
int msleep( int milliseconds )
{
struct timespec t;
t.tv_sec = milliseconds / 1000;
t.tv_nsec = ( milliseconds % 1000 ) * 1000000;
return nanosleep( &t, NULL );
}
//
// ワーカースレッド
//
void* worker_thread( void* param )
{
printf( "ThreadID: %x, started\n", pthread_self() );
// 同じ処理を繰り返す
for ( ;; )
{
printf( "ThreadID: %x, wait for resource\n", pthread_self() );
// ミューテックスに入る
pthread_mutex_lock( &mutex );
printf( "ThreadID: %x, access to resource\n", pthread_self() );
// global_valueをインクリメントする(1回あたり250ミリ秒費やす)
int work_value = global_value;
msleep( 250 );
work_value++;
global_value = work_value;
printf( "ThreadID: %x, release resource\n", pthread_self() );
// ミューテックスを出る
pthread_mutex_unlock( &mutex );
msleep( 100 );
}
return NULL;
}
//
// 主スレッド
//
int main( void )
{
printf( "mutex sample start\n" );
// ミューテックスオブジェクトを初期化する
// (属性はデフォルトのものを使用する)
pthread_mutex_init( &mutex, NULL );
// 処理を始める前の値を表示
global_value = 0;
printf( "initial global_value: %d\n", global_value );
// ワーカースレッドを10本作成し、50ミリ秒おきに起動
for ( int index = 0; index < THREAD_COUNT; index++ )
{
pthread_create( &threads[index], NULL, worker_thread, NULL );
msleep( 50 );
}
// 主スレッドは3秒間待機する
msleep( 3000 );
// 全ワーカースレッドを中断する
for ( int index = 0; index < THREAD_COUNT; index++ )
{
pthread_cancel( threads[index] );
printf( "ThreadID: %x, canceled\n", threads[index] );
}
// 処理を行った後の値を表示
printf( "after global_value: %d\n", global_value );
// ミューテックスオブジェクトを破棄する
pthread_mutex_destroy(&mutex);
return 0;
}
実行例
mutex sample start initial global_value: 0 ThreadID: b7e14b90, started ThreadID: b7e14b90, wait for resource ThreadID: b7e14b90, access to resource ThreadID: b7613b90, started ThreadID: b7613b90, wait for resource ThreadID: b6e12b90, started ThreadID: b6e12b90, wait for resource ThreadID: b6611b90, started ThreadID: b6611b90, wait for resource ThreadID: b5e10b90, started ThreadID: b5e10b90, wait for resource ThreadID: b7e14b90, release resource ThreadID: b7613b90, access to resource ThreadID: b560fb90, started ThreadID: b560fb90, wait for resource ThreadID: b4e0eb90, started ThreadID: b4e0eb90, wait for resource ThreadID: b7e14b90, wait for resource ThreadID: b460db90, started ThreadID: b460db90, wait for resource ThreadID: b3e0cb90, started ThreadID: b3e0cb90, wait for resource ThreadID: b360bb90, started ThreadID: b360bb90, wait for resource ThreadID: b7613b90, release resource ThreadID: b6e12b90, access to resource ThreadID: b7613b90, wait for resource ThreadID: b6e12b90, release resource ThreadID: b6611b90, access to resource ThreadID: b6e12b90, wait for resource ThreadID: b6611b90, release resource ThreadID: b5e10b90, access to resource ThreadID: b6611b90, wait for resource ThreadID: b5e10b90, release resource ThreadID: b560fb90, access to resource ThreadID: b5e10b90, wait for resource ThreadID: b560fb90, release resource ThreadID: b4e0eb90, access to resource ThreadID: b560fb90, wait for resource ThreadID: b4e0eb90, release resource ThreadID: b7e14b90, access to resource ThreadID: b4e0eb90, wait for resource ThreadID: b7e14b90, release resource ThreadID: b460db90, access to resource ThreadID: b7e14b90, wait for resource ThreadID: b460db90, release resource ThreadID: b3e0cb90, access to resource ThreadID: b460db90, wait for resource ThreadID: b3e0cb90, release resource ThreadID: b360bb90, access to resource ThreadID: b3e0cb90, wait for resource ThreadID: b360bb90, release resource ThreadID: b7613b90, access to resource ThreadID: b360bb90, wait for resource ThreadID: b7613b90, release resource ThreadID: b6e12b90, access to resource ThreadID: b7613b90, wait for resource ThreadID: b6e12b90, release resource ThreadID: b6611b90, access to resource ThreadID: b6e12b90, wait for resource ThreadID: b7e14b90, canceled ThreadID: b7613b90, canceled ThreadID: b6e12b90, canceled ThreadID: b6611b90, canceled ThreadID: b5e10b90, canceled ThreadID: b560fb90, canceled ThreadID: b4e0eb90, canceled ThreadID: b460db90, canceled ThreadID: b3e0cb90, canceled ThreadID: b360bb90, canceled after global_value: 13