C++11多线程生产者消费者模型竞态条件修复问题求助
问题根源
该实现存在三个核心错误:
- 共享变量
done的修改未加锁保护,属于跨线程无锁读写的未定义行为 - 消费者外层循环判断逻辑错误:当生产者将
done设为true后,消费者直接跳出外层循环,未处理队列中剩余的未消费元素 - 条件变量
wait未加谓词判断,可能出现虚假唤醒导致逻辑异常
修复后的完整代码
#include <iostream> #include <thread> #include <condition_variable> #include <mutex> #include <queue> using namespace std; int main() { int c = 0; bool done = false; queue<int> goods; mutex mtx; condition_variable cond_var; // 生产者线程 thread producer([&]() { for (int i = 0; i < 500; ++i) { unique_lock<mutex> lock(mtx); goods.push(i); c++; lock.unlock(); cond_var.notify_one(); } // 修改共享变量done必须加锁保护 unique_lock<mutex> lock(mtx); done = true; lock.unlock(); cond_var.notify_one(); }); // 消费者线程 thread consumer([&]() { unique_lock<mutex> lock(mtx); // 循环条件调整:只要生产未结束、或队列还有未消费元素就继续运行 while (!done || !goods.empty()) { // 只有队列为空时才进入等待,避免跳过未处理元素 if (goods.empty()) { // wait加谓词自动过滤虚假唤醒,保证醒来时要么生产结束、要么队列有元素可处理 cond_var.wait(lock, [&](){ return done || !goods.empty(); }); } // 批量处理队列中所有可用元素 while (!goods.empty()) { goods.pop(); c--; } } }); producer.join(); consumer.join(); cout << "Net: " << c << endl; return 0; }
核心修复点说明
- 所有对共享变量
done、goods队列、计数器c的读写操作都放在互斥锁的保护范围内,彻底消除竞态条件 - 调整消费者外层循环判断逻辑,保证生产者标记生产结束后,消费者依然会处理完队列中剩余的所有元素
- 优化条件变量等待逻辑,只有队列为空时才调用等待接口,同时通过谓词判断规避虚假唤醒问题,保证逻辑可靠性
内容的提问来源于stack exchange,提问作者pepe1
相关产品推荐
相关产品推荐

