You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含for循环的双线程条件变量未触发问题求助

问题分析与解决方案

嘿,我来帮你拆解下这个问题!你的核心问题出在互斥锁的作用范围上,咱们一步步理清楚:

为什么for循环里条件变量通知无效?

你在simulate_event_readin函数开头就声明了std::lock_guard<std::mutex> lck(mtx),这意味着从函数开始到结束,整个for循环的全程,互斥锁都被线程一牢牢攥在手里。而线程二的condVar.wait()必须先拿到互斥锁,才能检查event_angekommen的状态——但锁一直被线程一占着,线程二根本抢不到锁,自然就永远卡在等待状态,连条件都没法检查,更别说响应通知了。

至于去掉for循环后能工作,是因为线程一执行完函数就释放了锁,线程二能顺利获取锁并检查到event_angekommen为true,所以能触发一次处理逻辑。

修正方案

我们需要调整锁的作用范围,只在修改共享数据(csv_reihe和event_angekommen)的时候加锁,其他时间(比如sleep的时候)释放锁,让线程二能正常工作。另外还要给线程二加个退出逻辑,避免CSV处理完后线程二无限等待。

修正后的线程一代码

std::mutex mtx;
std::condition_variable condVar;
bool event_angekommen{false};
bool stop_processing{false}; // 新增结束标志,用来通知线程二退出

void simulate_event_readin(CSVLeser leser, int sekunden, std::vector<std::string> &csv_reihe) {
    std::vector<std::vector<std::string>> csv_daten = leser.erhalteDatenobj();
    for (size_t idx = 1; idx < csv_daten.size(); idx++) {
        // sleep的时候不需要锁,先释放锁让线程二有机会运行
        std::this_thread::sleep_for(std::chrono::seconds(sekunden));
        
        // 只在修改共享数据时加锁,修改完成后自动释放锁
        std::lock_guard<std::mutex> lck(mtx);
        csv_reihe = csv_daten[idx];
        event_angekommen = true;
        condVar.notify_one();
    }
    
    // 所有CSV行处理完毕,通知线程二退出循环
    std::lock_guard<std::mutex> lck(mtx);
    stop_processing = true;
    condVar.notify_one();
}

修正后的线程二代码

void detektiere_events(Detektion detektion, std::vector<std::string> &csv_reihe, std::vector<std::string> &pir_events) {
    while(true) {
        std::cout<<"Warte"<<std::endl;
        std::unique_lock<std::mutex> lck(mtx);
        // 等待新数据或者结束信号
        condVar.wait(lck, [] {return event_angekommen || stop_processing; });
        
        // 收到结束信号就退出循环
        if(stop_processing) {
            std::cout<<"Verarbeitung beendet."<<std::endl;
            break;
        }
        
        // 重置事件标志,避免下次wait直接触发(防止重复处理同一行数据)
        event_angekommen = false;
        std::cout<<"Detektiere Events"<<std::endl;
        
        std::string externes_event_user_id = csv_reihe[4];
        std::string externes_event_data = csv_reihe[6];
        detektion.neues_event(externes_event_data, externes_event_user_id);
        
        if(detektion.pruefe_Pir_id()) {
            pir_events.push_back(externes_event_data);
        }
    }
}

关键说明

  1. 缩小锁的作用范围:线程一只有在更新共享数据和发送通知时才持有锁,sleep期间锁是释放的,线程二可以正常获取锁并等待通知。
  2. 新增结束标志:当线程一处理完所有CSV行后,通过stop_processing通知线程二退出循环,避免线程二无限等待。
  3. 重置事件标志:线程二每次处理完数据后把event_angekommen设为false,确保下次wait会等待新的通知,不会重复处理同一行数据。

内容的提问来源于stack exchange,提问作者s kop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 00:12:29