C++类成员condition_variable实现生产消费场景触发段错误问题求解
问题原因分析
- 核心故障点:成员函数内创建线程的lambda使用
[&]作为捕获列表,无法合法捕获当前对象的this指针。this是成员函数作用域内的纯右值,不支持引用捕获,导致lambda内调用成员函数、访问mu/cond/stored等成员变量时使用野指针,触发非法内存访问,最终出现段错误。 - 其他引发未定义行为的问题:
- 缺失必要标准头文件:代码使用了
std::chrono时间接口、std::cin、随机数接口、时间戳接口,但未引入对应的<chrono>、<iostream>、<cstdlib>、<ctime>头文件,依赖编译器非标准的隐式头文件引入逻辑,可能触发各类未知异常。 - 随机数初始化逻辑错误:
srand()仅需全局执行一次,放在Producer函数中会被多线程同时调用,存在数据竞争,同时time(0)精度为秒,重复调用会导致随机种子被反复覆盖,生成的随机数重复。 - 线程对象存在管理隐患:
Consumer中创建的生产者调度线程pl未显式设置detach()或join(),若后续逻辑改动导致Consumer提前退出,std::thread析构时会直接调用terminate()终止程序。
- 缺失必要标准头文件:代码使用了
修复方案
- 所有涉及成员访问的lambda显式捕获
this指针,替换原有的[&]引用捕获写法,保证成员访问的合法性。 - 补充所有缺失的标准头文件,消除编译器依赖。
- 将
srand()初始化逻辑移到类构造函数中,仅执行一次,避免多线程竞争和重复初始化。 - 对后台运行的调度线程显式调用
detach(),消除线程对象管理隐患。
修正后完整代码
#include <thread> #include <condition_variable> #include <deque> #include <chrono> #include <iostream> #include <cstdlib> #include <ctime> class Multi_Thread_Test{ public: std::mutex mu; std::condition_variable cond; std::deque<int> stored; Multi_Thread_Test(){ // 随机种子仅初始化一次 srand(time(0)); } void Producer(){ std::unique_lock<std::mutex> locker(mu); stored.push_back(rand()); locker.unlock(); cond.notify_one(); } void Producer_loop(){ while(true){ // 显式捕获this指针 std::thread t1([this]{Producer();}); std::thread t2([this]{Producer();}); t1.join(); t2.join(); std::this_thread::sleep_for(std::chrono::seconds(5)); } } void Consumer() { // 显式捕获this指针,后台线程detach std::thread pl([this]{this->Producer_loop();}); pl.detach(); while (true) { std::unique_lock<std::mutex> locker(mu); cond.wait(locker, [this] { return !stored.empty(); }); int temp = stored.front(); stored.pop_front(); locker.unlock(); // 可在此处添加自定义消费逻辑 } } }; int main() { Multi_Thread_Test test; test.Consumer(); std::cin.get(); std::cin.get(); return 0; }
内容的提问来源于stack exchange,提问作者Amir Rasti
相关产品推荐
相关产品推荐

