C++多线程下同时操作vector push_back与遍历是否安全及同步方案
问题解答
1. 原代码是否安全?
不安全。STL 的std::vector本身不提供线程安全保障,并发读写/写写操作属于数据竞争,是C++标准明确定义的未定义行为,会出现各种不可预期的问题。
2. 范围for循环的编译逻辑是否如你所述?
是的。C++标准明确规定范围for的语义就是等价于你贴出的迭代器遍历逻辑:先获取容器的begin()和end()迭代器,再循环判断迭代器是否相等、递增、解引用取值,完全符合你给出的伪代码逻辑。
3. push_back触发内存重分配是否会导致迭代器失效崩溃?
会。当push_back触发内存重分配时,vector会申请新的更大的内存块,把原有元素拷贝/移动过去后,直接释放旧的内存块,此时所有指向旧内存的迭代器(包括遍历线程已经获取的__begin迭代器)全部失效,遍历线程解引用失效迭代器的行为就是典型的野指针访问,大概率直接触发段错误崩溃,即使没有立即崩溃也会读到脏数据,逻辑完全不可控。
就算没有触发内存重分配,push_back操作会修改vector的大小,也就是会修改end()迭代器的值,此时遍历线程读取end()、判断__begin != __end的操作也属于并发读写冲突,同样是未定义行为,一样会出问题。
4. 你给出的加互斥锁的写法是否可行?
基础逻辑是正确的,只要保证所有对v的读写操作都持有同一个互斥锁,就可以完全避免数据竞争问题。
不过更推荐用RAII 风格的锁包装器代替手动lock()/unlock(),可以避免操作中途抛出异常时没有释放锁导致的死锁问题,优化后的写法如下:
#include <mutex> std::mutex mtx; vector<int> v; void thread_1() { std::lock_guard<std::mutex> lock(mtx); // 构造时自动加锁,出作用域自动解锁 v.push_back(100); } void thread_2() { std::lock_guard<std::mutex> lock(mtx); for (int i : v) { // 执行相关操作 } }
内容的提问来源于stack exchange,提问作者ibse
相关产品推荐
相关产品推荐

