生产者生产单个项目后无法通知消费者,如何用Semaphore修复?
问题分析与修复方案
原代码的核心问题并非信号量的通知逻辑错误,而是共享队列未做线程安全保护:生产者与消费者对std::queue的并发操作存在数据竞争,加上线程调度的不确定性,导致消费者无法及时感知到生产者添加的单个元素,直到缓冲区被填满。结合Semaphore和互斥锁可以解决这个问题。
修复后的代码
#include <iostream> #include <queue> #include <semaphore.h> #include <thread> #include <functional> #include <mutex> #include <ctime> const int BUFFER_SIZE = 3; class Buffer { public: sem_t sem_available_slots; // 可用空位数量 sem_t sem_available_items; // 已生产元素数量 std::queue<int> buffer; std::mutex mtx; // 保护队列的互斥锁 Buffer() { sem_init(&sem_available_slots, 0, BUFFER_SIZE); sem_init(&sem_available_items, 0, 0); } ~Buffer() { sem_destroy(&sem_available_slots); sem_destroy(&sem_available_items); } void producer() { for (int i = 0; i < BUFFER_SIZE; ++i) { sem_wait(&sem_available_slots); // 等待有空位 int item = rand() % 10; // 加锁后操作队列,避免数据竞争 std::lock_guard<std::mutex> lock(mtx); buffer.push(item); std::cout << "Producer added " << item << std::endl; sem_post(&sem_available_items); // 通知消费者有新元素 } std::cout << "Producer finished all items, terminating thread" << std::endl; } void consumer() { for (int i = 0; i < BUFFER_SIZE; ++i) { sem_wait(&sem_available_items); // 等待有元素可消费 // 加锁后操作队列 std::lock_guard<std::mutex> lock(mtx); int item = buffer.front(); buffer.pop(); std::cout << "Consumer removed " << item << std::endl; sem_post(&sem_available_slots); // 通知生产者有空位 } std::cout << "Consumer finished all items, terminating thread" << std::endl; } }; int main() { srand(time(nullptr)); // 初始化随机数种子 Buffer buffer; std::thread producer_thread(&Buffer::producer, &buffer); std::thread consumer_thread(&Buffer::consumer, &buffer); producer_thread.join(); consumer_thread.join(); return 0; }
关键修改说明
- 添加线程安全保护:用
std::mutex和std::lock_guard包裹所有对buffer的操作,确保同一时间只有一个线程能访问队列,彻底解决数据竞争问题。 - 信号量逻辑优化:重命名信号量为
sem_available_slots和sem_available_items,分别对应缓冲区空位和已生产元素数量,逻辑更直观,避免命名混淆。 - 调整循环逻辑:将原无限循环改为固定次数循环,明确生产/消费的元素总量,避免线程异常阻塞或无限运行。
- 初始化随机数种子:确保每次运行生成不同的随机元素,便于观察执行效果。
修复后,生产者每生产一个元素就会立即唤醒消费者,消费者无需等待缓冲区填满即可开始消费,完全符合生产者-消费者的同步预期。
内容的提问来源于stack exchange,提问作者user2997518
相关产品推荐
相关产品推荐

