我正在C中编写一个生产者 - 消费者线程程序。我程序中的所有内容都完美地处理了一个主要的异常。当我有多个消费者线程时(几乎总是如此),只有第一个消费者线程才会实际终止。我已经尝试了所有我能想到的东西,但问题仍然存在。这是我的代码,它的内容被剥离了,所以你只能看到相关的部分。
我可以从输出中看到两个终止条件变量都变为零,这当然是第一个消费者线程终止的原因。但为什么其他消费者线程也不会终止呢?
谢谢!
sem_t full, empty, mutex;
int threads;
int to_consume;
FILE* inputfp[5];
FILE* outputfp = NULL;
char in[BUF];
void* p(void* inpFile) {
while (fscanf(inpFile, FMTSTRING, in) > 0) {
sem_wait(&empty);
sem_wait(&mutex);
// production code here
to_consume++;
sem_post(&mutex);
sem_post(&full);
}
fclose (inpFile);
sem_wait(&mutex);
threads--;
sem_post(&mutex);
return NULL;
}
void* c() {
int continuing = 1;
while (continuing) {
sem_wait(&full);
sem_wait(&mutex);
//consumption code here
to_consume--;
fprintf("%d %d\n", threads, to_consume); //these both go to zero by the end
if ( (threads <= 0) && (to_consume <= 0) ) {
continuing = 0;
}
sem_post(&mutex);
sem_post(&empty);
}
return NULL;
}
int main (int argc, char* argv[]) {
int i;
int con_threads;
con_threads = 3;
to_consume = 0;
pthread_t *pr_thread[argc-2];
pthread_t *con_thread[2];
sem_init(&full, 0, 0);
sem_init(&empty, 0, 50);
sem_init(&mutex, 0, 1);
for (i = 0; i < (argc-2); i++) {
pr_thread[i] = (pthread_t *) malloc(sizeof(pthread_t));
inputfp[i] = fopen(argv[i+1], "r");
int rc = pthread_create (pr_thread[i], NULL, p, inputfp[i]);
sem_wait(&mutex);
threads++;
sem_post(&mutex);
}
outputfp = fopen(argv[(argc-1)], "wb");
for (i = 0; i con_threads 3; i++) {
con_thread[i] = (pthread_t *) malloc(sizeof(pthread_t));
int rc = pthread_create (con_thread[i], NULL, c, NULL);
}
for (i = 0; i < (argc - 2); i++) {
pthread_join(*pr_thread[i], 0);
free(pr_thread[i]);
}
for (i = 0; i con_threads 3; i++) {
fprintf(stderr, "About to close consumer thread %d.\n", i);
pthread_join(*res_thread[i], 0);
fprintf(stderr, "Consumer thread %d closed successfully.\n", i);
free(res_thread[i]);
}
printf ("About to close the output file.\n");
/* Close the output file */
fclose (outputfp);
return EXIT_SUCCESS;
}
答案 0 :(得分:1)
我认为您的问题是,当第一个消费者检测到没有剩余线程时,您不会再次发布full
,因此第二个消费者正在等待full
,但信号将永远不会到达。您可能需要对消费者进行计数,但是对于第一遍(概念证明),您可以将full
留给永远不会阅读的帖子。