使用pthread与信号量实现多生产者消费者问题最后消费卡住如何解决
故障原因
- 消费者循环判断存在竞态:
while (count < NO_ITEMS)的判断是在持有互斥锁、调用sem_wait前执行的,此时共享变量count可能还未被其他消费者线程更新,会出现多个消费者同时通过判断进入循环的情况。生产者总共只会触发NO_ITEMS次sem_post(&fillCount),当进入循环的消费者数量超过剩余的fillCount信号量时,多余的线程会永久阻塞在sem_wait调用上。 - 消费逻辑判断错误:代码中
if (!items.empty() && count < NO_ITEMS - 1)的条件限制了只有count小于99时才会消费商品,导致第100个商品永远不会被弹出处理。且count无论是否实际完成消费都会自增,进一步导致退出逻辑和信号量计数不匹配。 - 全局
count语义错误:当前count统计的是消费者进入临界区的次数,而非实际消费的商品总数,和生产端的总商品数无法对应,逻辑完全混乱。
修复方案
调整消费者逻辑,将消费计数、退出判断放到持有互斥锁之后执行,修正消费条件,同时处理阻塞消费者的唤醒逻辑,修改后的消费者函数参考如下:
void* thread_consumer(void* args) { while (1) { sem_wait(&fillCount); pthread_mutex_lock(&mutex); // 所有商品已消费完成,唤醒其他阻塞的消费者后退出 if (count >= NO_ITEMS) { pthread_mutex_unlock(&mutex); sem_post(&fillCount); break; } // 正常消费逻辑,消费完成后再更新计数 removeItem(); count++; pthread_mutex_unlock(&mutex); sem_post(&emptyCount); } return nullptr; }
修改后逻辑说明:
- 先通过
sem_wait拿到可用商品的信号量,再进入临界区判断状态,避免无效的信号量等待。 - 临界区内判断如果所有商品已经消费完成,就主动post一次
fillCount唤醒其他阻塞的消费者,避免其他线程永久等待。 - 移除错误的消费限制条件,只有实际完成消费才更新计数
count,保证计数语义正确。
内容的提问来源于stack exchange,提问作者SugiuraAyano
相关产品推荐
相关产品推荐

