生产者-消费者计数器代码出现异常输出问题求助
生产者-消费者交替计数器逻辑问题
我用生产者-消费者模式实现了一个交替运行的计数器,预期计数从0到10共打印10次。但运行时每次计数打印之间会出现大量锁、解锁及信号相关的打印信息,怀疑代码逻辑有问题。
按照预期,生产者和消费者的每次迭代是否应该仅各执行一次锁、解锁和信号操作?
运行输出示例
myCount: 6 -> 7 Producer: signaling myCond1 Producer: waiting on myCond2 CONSUMER: myMutex locked CONSUMER: signaling myCond2 CONSUMER: myMutex unlocked Producer: myMutex unlocked Producer: myMutex locked CONSUMER: myMutex locked CONSUMER: signaling myCond2 CONSUMER: myMutex unlocked myCount: 7 -> 8 Producer: signaling myCond1 Producer: waiting on myCond2 CONSUMER: myMutex locked CONSUMER: signaling myCond2 CONSUMER: myMutex unlocked Producer: myMutex unlocked Producer: myMutex locked CONSUMER: myMutex locked CONSUMER: signaling myCond2 CONSUMER: myMutex unlocked myCount: 8 -> 9 Producer: signaling myCond1 Producer: waiting on myCond2 CONSUMER: myMutex locked CONSUMER: signaling myCond2 CONSUMER: myMutex unlocked Producer: myMutex unlocked Producer: myMutex locked CONSUMER: myMutex locked CONSUMER: signaling myCond2 CONSUMER: myMutex unlocked myCount: 9 -> 10 Producer: signaling myCond1 Producer: waiting on myCond2 CONSUMER: myMutex locked CONSUMER: signaling myCond2 Producer: myMutex unlocked Producer: myMutex locked PROGRAM END
代码实现
#include <stdio.h> #include <stdlib.h> #include <pthread.h> // Global variables pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t myCond1 = PTHREAD_COND_INITIALIZER; pthread_cond_t myCond2 = PTHREAD_COND_INITIALIZER; int myCount = 0; // Function prototypes void* producerThread(void* arg); void* consumerThread(void* arg); int main() { // Create consumer thread pthread_t consumer; printf("PROGRAM START\n"); if (pthread_create(&consumer, NULL, consumerThread, NULL) != 0) { perror("Error creating consumer thread"); exit(EXIT_FAILURE); } // Run the producer thread producerThread(NULL); // Wait for the consumer thread to finish pthread_join(consumer, NULL); printf("PROGRAM END\n"); return 0; } void* producerThread(void* arg) { while (1) { printf("Producer: myMutex locked\n"); pthread_mutex_lock(&myMutex); if (myCount >= 10) { pthread_mutex_unlock(&myMutex); break; // Terminate the program when myCount reaches 10 } myCount++; printf("myCount: %d -> %d\n", myCount - 1, myCount); // Signal the consumer that a new value is available printf("Producer: signaling myCond1\n"); pthread_cond_signal(&myCond1); printf("Producer: waiting on myCond2\n"); pthread_cond_wait(&myCond2, &myMutex); pthread_mutex_unlock(&myMutex); printf("Producer: myMutex unlocked\n"); } return NULL; } void* consumerThread(void* arg) { printf("CONSUMER THREAD CREATED\n"); while (1) { pthread_mutex_lock(&myMutex); printf("CONSUMER: myMutex locked\n"); // Wait for the producer to signal that a new value is available while (myCount == 0) { printf("CONSUMER: waiting on myCond1\n"); pthread_cond_wait(&myCond1, &myMutex); } // Signal the producer that the value has been consumed printf("CONSUMER: signaling myCond2\n"); pthread_cond_signal(&myCond2); if (myCount >= 10) { pthread_mutex_unlock(&myMutex); break; // Terminate the program when myCount reaches 0 } pthread_mutex_unlock(&myMutex); printf("CONSUMER: myMutex unlocked\n"); } return NULL; }
问题分析与修复
核心问题
- 锁操作顺序错误:生产者先打印锁已获取的信息,再实际调用
pthread_mutex_lock,导致打印状态与实际锁状态不符;且生产者在pthread_cond_wait返回后直接解锁,下一次循环立刻重新加锁,触发无意义的线程切换。 - 消费者循环逻辑冗余:消费者每次循环无条件加锁,即使
myCount已达10,仍会重复执行加锁、发信号、解锁操作,直到生产者退出。 - 终止逻辑混乱:消费者注释标注"计数到0时退出",但实际判断条件是
myCount >=10,逻辑不一致。
预期正确流程
每次迭代应严格交替:
- 生产者:加锁 → 计数递增 → 通知消费者 → 等待消费者确认 → 解锁
- 消费者:加锁 → 等待生产者通知 → 通知生产者 → 解锁
两者各执行一次锁、解锁、信号操作。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t myCond1 = PTHREAD_COND_INITIALIZER; // 生产者通知消费者 pthread_cond_t myCond2 = PTHREAD_COND_INITIALIZER; // 消费者通知生产者 int myCount = 0; int done = 0; // 标记生产是否结束 void* producerThread(void* arg) { while (1) { pthread_mutex_lock(&myMutex); if (myCount >= 10) { done = 1; pthread_cond_signal(&myCond1); // 通知消费者退出 pthread_mutex_unlock(&myMutex); break; } myCount++; printf("myCount: %d -> %d\n", myCount - 1, myCount); pthread_cond_signal(&myCond1); // 通知消费者处理新计数 printf("Producer: signaling myCond1, waiting on myCond2\n"); pthread_cond_wait(&myCond2, &myMutex); // 等待消费者确认 pthread_mutex_unlock(&myMutex); } printf("Producer thread exit\n"); return NULL; } void* consumerThread(void* arg) { printf("CONSUMER THREAD CREATED\n"); while (1) { pthread_mutex_lock(&myMutex); // 仅在无新计数且未结束时等待 while (myCount == 0 && !done) { printf("CONSUMER: waiting on myCond1\n"); pthread_cond_wait(&myCond1, &myMutex); } // 检测到结束信号则退出 if (done) { pthread_mutex_unlock(&myMutex); break; } printf("CONSUMER: signaling myCond2\n"); pthread_cond_signal(&myCond2); // 通知生产者继续生产 pthread_mutex_unlock(&myMutex); } printf("Consumer thread exit\n"); return NULL; } int main() { pthread_t consumer; printf("PROGRAM START\n"); if (pthread_create(&consumer, NULL, consumerThread, NULL) != 0) { perror("Error creating consumer thread"); exit(EXIT_FAILURE); } producerThread(NULL); pthread_join(consumer, NULL); printf("PROGRAM END\n"); return 0; }
修复说明
- 修正锁操作顺序:生产者先加锁再打印状态,确保信息准确。
- 新增结束标记
done:明确告知消费者生产已完成,避免无意义循环。 - 优化消费者等待逻辑:仅在需要时等待,减少冗余的锁操作。
- 对齐终止逻辑:生产者完成后主动通知消费者退出,避免线程僵死。
修复后,每次计数变化只会对应一次生产者和消费者的锁、解锁、信号操作,不会出现多余的打印信息。
内容的提问来源于stack exchange,提问作者Ahmed Zaidan
相关产品推荐
相关产品推荐

