- ベストアンサー
pthread_cond_wait 取りこぼし?
はじめまして。 pthreadのお勉強がてら、パイプライン処理を実装してみようととりあえず実証コードを書いてみましたが、うまく意図した動きをしてくれません。 やりたいことは、処理ステージが2つあって、メインからステージ1をキックし、ステージ1は自分の処理が終わったらステージ2をキックするといった動作です。(メイン、ステージ1、ステージ2を並列に動作させたい) 取りあえず連鎖的に動作するか試したいだけなので、ステージ間のデータの受け渡しとかは、後で考えるとします。 それで、以下のような単純なコードを書きました。 期待する結果は、最後に表示される数値が 10000, 10000, 10000 になることですが、実際は、10000, 4401, 4401 のようにステージ1,2が少なくなります。 一応、それなりに調べて条件変数のセオリーに従い書いたつもりなのですが、どうしてこうなるか、ご教授ください。 test.c (空白を全角にしてあります) ------ #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> pthread_mutex_t mutex1, mutex2; pthread_cond_t cond1, cond2; int ready1, ready2; int end1, end2; int count1, count2; void * stage1( void *arg ) { pthread_mutex_lock( &mutex1 ); while( 1 ) { /* wait for my signal & job */ while ( ready1 == 0 ) { pthread_cond_wait( &cond1, &mutex1 ); } if ( end1 == 1 ){ /* is shutdown thread */ break; } /* my job. */ count1++; /* job clear */ ready1 = 0; /* forward next stage */ pthread_mutex_lock( &mutex2 ); ready2 = 1; pthread_cond_signal( &cond2 ); pthread_mutex_unlock( &mutex2 ); } pthread_mutex_unlock( &mutex1 ); return NULL; } void * stage2( void *arg ) { pthread_mutex_lock( &mutex2 ); while( 1 ) { while ( ready2 == 0 ) { pthread_cond_wait( &cond2, &mutex2 ); } if ( end2 == 1 ){ break; } count2++; ready2 = 0; } pthread_mutex_unlock( &mutex2 ); return NULL; } int main( ) { int i; pthread_t t1, t2; pthread_mutex_init( &mutex1, 0 ); pthread_cond_init ( &cond1, 0 ); ready1 = 0; end1 = 0; count1 = 0; pthread_create( &t1, 0, stage1, NULL ); pthread_mutex_init( &mutex2, 0 ); pthread_cond_init ( &cond2, 0 ); ready2 = 0; end2 = 0; count2 = 0; pthread_create( &t2, 0, stage2, NULL ); for ( i=0; i<10000; i++ ){ pthread_mutex_lock( &mutex1 ); ready1 = 1; pthread_cond_signal( &cond1 ); pthread_mutex_unlock( &mutex1 ); } pthread_mutex_lock( &mutex1 ); ready1 = 1; end1 = 1; pthread_cond_signal( &cond1 ); pthread_mutex_unlock( &mutex1 ); pthread_join(t1, 0 ); pthread_cond_destroy( &cond1 ); pthread_mutex_destroy( &mutex1 ); pthread_mutex_lock( &mutex2 ); ready2 = 1; end2 = 1; pthread_cond_signal( &cond2 ); pthread_mutex_unlock( &mutex2 ); pthread_join(t2, 0 ); pthread_cond_destroy( &cond2 ); pthread_mutex_destroy( &mutex2 ); printf("%d, %d, %d\n", i, count1, count2); return 0; } ------ gcc -o test -lpthread test.c 以上
- みんなの回答 (4)
- 専門家の回答
お礼
再度のご回答ありがとうございます。 下記のようにすると同期しますが、仰る通り遅くなりますね。 実際にはステージ間にバッファ(キュー)を入れてクッションを作るようにしないと駄目なことが想像できました。 ------ for ( i=0; i<10000; i++ ){ while ( ready1 == 1 ){ sched_yield(); } pthread_mutex_lock( &mutex1 ); ready1 = 1; pthread_cond_signal( &cond1 ); pthread_mutex_unlock( &mutex1 ); } ------