全局std::vector<std::future<int>>引发的异步调用异常行为排查
问题原因分析
全局容器的线程安全隐患:
std::vector并非线程安全容器,当多个线程同时对全局的vect执行修改操作(比如通过std::move移入元素、调用push_back)时,会引发数据竞争,进而导致未定义行为。你看到第一个future状态变为empty,就是数据竞争破坏对象内部状态的典型表现。局部变量的执行逻辑差异:当
vect作为func内的局部变量时,通常是主线程先完成所有future的移入操作,再启动子线程;或者子线程仅对vect做读取操作,不存在并发修改。这种单线程修改+多线程只读的场景下,没有数据竞争,程序自然能正常运行。std::future的移动特性影响:std::future是移动语义专属类型,对象被移动后原实例会变为empty状态。如果并发修改vector时(比如扩容过程中元素的移动出现异常),第一个future被意外重复移动,就会导致它的状态提前变为empty,后续调用get()时触发崩溃。
简单解决建议
- 若要多线程共享
vect,必须给所有读写操作加同步保护,比如用std::mutex包裹对vect的访问代码:std::mutex mtx; // 写入操作 { std::lock_guard<std::mutex> lock(mtx); vect.emplace_back(std::move(some_future)); } // 读取操作 { std::lock_guard<std::mutex> lock(mtx); auto res = vect[0].get(); } - 优先在主线程完成
vector的初始化和所有future的移入操作,再让子线程仅读取vect,从根源避免并发修改。
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

