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

多线程下向std::vector执行push_back时,其他线程读取是否存在竞态条件?

多线程下std::vector的读写安全性问题

这段代码完全不安全,你的判断是正确的,确实存在严重的竞态条件和未定义行为,原因如下:

  1. 扩容导致迭代器失效
    当foo()中的push_back()触发vector扩容时(即当前容量不足以容纳新元素),vector会重新分配一块更大的内存,将原有元素拷贝过去后释放旧内存。此时g()中范围for循环依赖的begin()和end()迭代器会直接失效,后续用这些失效迭代器访问内存属于未定义行为,可能引发程序崩溃、读取垃圾数据等问题。

  2. size变化引发遍历边界混乱
    即使没有触发扩容,push_back()会修改vector的size()成员变量。范围for循环的底层逻辑是先获取begin()和end()(后者的位置由size决定),然后遍历。如果遍历过程中另一个线程修改了size,会导致遍历的边界发生变化,可能出现多读取元素、读取未初始化内存,或者遍历提前终止等异常情况。

  3. C++标准对容器线程安全的规定
    根据C++标准,std::vector不属于线程安全容器:当有线程对容器执行修改操作(如push_back())时,其他线程不能同时执行读取或修改操作,否则会构成数据竞争,直接触发未定义行为。


正确的处理方式

  • 加互斥锁同步:给vector搭配std::mutex,在foo()执行push_back()前后加锁,g()执行遍历操作前后也加锁,确保同一时间只有一个线程访问vector。示例代码:
#include <mutex>
#include <vector>

std::mutex mtx;
std::vector<int> v;

void foo() {
  std::lock_guard<std::mutex> lock(mtx);
  v.push_back(1);
}

void g() {
  std::lock_guard<std::mutex> lock(mtx);
  for(const auto& elem : v) {
    // 读取操作
  }
}
  • 使用线程安全容器:如果项目允许,可以使用第三方线程安全容器(如基于互斥锁封装的自定义线程安全vector,或成熟的第三方库实现)替代std::vector。
  • 生产者-消费者模型:改用std::queue配合std::condition_variable实现生产者-消费者模式,避免直接对vector进行并发读写。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:37:44