使用pthread_cond_signal的生产者-消费者程序为何卡死?
生产者-消费者模型在n=1/2时卡死的问题求助
我用C语言的pthread库编写生产者-消费者程序,程序需要在限制n内生产和消费数据。但当n=1或n=2时,程序通常很快就会卡死——具体表现为停止输出'('或')',需要手动退出。
已制作最小可复现示例,测试发现n=1或2时会出现明显异常,n≥3时运行正常。
核心代码
#include "thread.h" #include <semaphore.h> int n, count = 0; pthread_mutex_t lk = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cv = PTHREAD_COND_INITIALIZER; void Tproduce(){ while(1){ pthread_mutex_lock(&lk); while(count == n){ pthread_cond_wait(&cv,&lk); } assert(count != n); printf("("); count++; //printf("%d\t", count); pthread_cond_signal(&cv); pthread_mutex_unlock(&lk); } } void Tconsume(){ while(1){ pthread_mutex_lock(&lk); while(count == 0){ pthread_cond_wait(&cv,&lk); } assert(count != 0); printf(")"); count--; //printf("%d\t",count); pthread_cond_signal(&cv); pthread_mutex_unlock(&lk); } } int main(int argc, char* argv[]){ assert(argc==2); n=atoi(argv[1]); setbuf(stdout,NULL); for(int i = 0; i < 8; i++){ create(Tproduce); create(Tconsume); } }
其中create是自制线程池中的线程创建函数,已验证可用。
尝试过的方案与疑问
我尝试使用pthread_cond_broadcast或两个独立的条件变量时,程序均可正常运行,但无法理解为何使用pthread_cond_signal会导致卡死。
按逻辑至少应有一个线程能正常工作,所有阻塞线程都应有被唤醒的机会。即使生产者或消费者线程被错误唤醒并尝试获取锁,也会因不满足条件而重新进入等待,让其他线程有机会获取锁。因此无论最坏情况如何,都不应完全卡死。
运行环境
- WSL2下的Ubuntu 20
- 编译器为gcc 9.4.0
补充:thread.h头文件代码
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdatomic.h> #include <assert.h> #include <unistd.h> #include <pthread.h> #define NTHREAD 64 enum { T_FREE = 0, T_LIVE, T_DEAD, }; struct thread { int id, status; pthread_t thread; void (*entry)(int); }; struct thread tpool[NTHREAD], *tptr = tpool; void *wrapper(void *arg) { struct thread *thread = (struct thread *)arg; thread->entry(thread->id); return NULL; } void create(void *fn) { assert(tptr - tpool < NTHREAD); *tptr = (struct thread) { .id = tptr - tpool + 1, .status = T_LIVE, .entry = fn, }; pthread_create(&(tptr->thread), NULL, wrapper, tptr); ++tptr; } void join() { for (int i = 0; i < NTHREAD; i++) { struct thread *t = &tpool[i]; if (t->status == T_LIVE) { pthread_join(t->thread, NULL); t->status = T_DEAD; } } } __attribute__((destructor)) void cleanup() { join(); }
恳请各位提供思路或解决方案。
内容的提问来源于stack exchange,提问作者Makise Kurisu
相关产品推荐
相关产品推荐

