Cのpthreadライブラリでは、単純なプロデューサ/コンシューマスキーマを実装しようとしています。プロデューサ/コンシューマキューの不安定なデッドロック
プロデューサーは、乱数を生成し、消費者はただの数字一つ一つを取り、それを標準出力に出力します。この
typedef struct {
int q[MAX_QUEUE];
int head;
int tail;
} queue;
のようにキューに入れます。同期は、mutex
と2つの条件変数empty_queue
(キューが空の場合はコンシューマをサスペンドする)とfull_queue
(キューがいっぱいの場合はプロデューサをサスペンドする)で行われます。問題は、両方のスレッドがMAX_QUEUE
の要素が生成/消費されたときに停止し、デッドロック状態になることです。私はすべてが正しいと思う、私は間違って何をしているのか分からない。
プロデューサー:
void* producer(void* args) {
unsigned seed = time(NULL);
int random;
queue *coda = (queue *) args;
while(1) {
Pthread_mutex_lock(&queue_lock);
while(coda->head == MAX_QUEUE-1) { // Full Queue
printf("Suspending producer\n");
fflush(stdout);
Pthread_cond_wait(&full_queue, &queue_lock);
}
random = rand_r(&seed) % 21;
enqueue(coda, random);
Pthread_cond_signal(&empty_queue);
Pthread_mutex_unlock(&queue_lock);
sleep(1);
}
return NULL;
}
消費者:
void* consumer(void* args) {
queue *coda = (queue *) args;
int elem;
while(1) {
Pthread_mutex_lock(&queue_lock);
while(coda->head == coda->tail) { // Empty Queue
printf("Suspending Consumer\n");
fflush(stdout);
Pthread_cond_wait(&empty_queue, &queue_lock);
}
elem = dequeue(coda);
printf("Found %i\n",elem);
Pthread_cond_signal(&full_queue);
Pthread_mutex_unlock(&queue_lock);
}
return NULL;
}
エンキュー/デキューは
static void enqueue(queue *q, int elem) {
q->q[(q->tail)] = elem;
(q->tail)++;
if(q->tail == MAX_QUEUE)
q->tail = 0;
}
static int dequeue(queue *q) {
int elem = q->q[(q->head)];
(q->head)++;
if(q->head == MAX_QUEUE)
q->head = 0;
return elem;
}
Pthread_ *ルーチン標準pthread_ *ライブラリ関数への単なるラッパー関数です。 (= 10 MAX_QUEUE付き) 出力:
Suspending Consumer
Found 16
Suspending Consumer
Found 7
Suspending Consumer
Found 5
Suspending Consumer
Found 6
Suspending Consumer
Found 17
Suspending Consumer
Found 1
Suspending Consumer
Found 12
Suspending Consumer
Found 14
Suspending Consumer
Found 11
Suspending Consumer
Suspending producer
'(coda-> tail + 1)%MAX_QUEUE == coda-> head'を使用して解決しました。提案していただきありがとうございます。 –