C++多线程操作queue时所有线程获取队列同一条数据问题求助
问题原因分析
- 队列值传递产生多份独立副本:你定义的
Test函数参数为值类型queue<string> queue,每个线程调用Test时都会完整拷贝主函数中的原队列,所有线程操作的是自己本地的队列副本,执行pop操作只会清空自己本地的副本,不会影响其他线程的队列数据,因此每个线程都会遍历输出全部队列元素,出现重复取到同一条数据的现象。 - 无同步机制导致线程安全问题:即使将参数改为引用传递让所有线程操作同一个队列,
std::queue本身也不具备线程安全特性,多线程同时执行empty()、front()、pop()操作会触发数据竞争,属于C++标准规定的未定义行为,依然会出现重复取数、程序异常崩溃等问题。 - 标准输出无同步保护:
std::cout本身不是线程安全的,多线程同时输出会导致内容乱序、字符拼接错误等异常。
解决方法
需要修改代码实现所有线程操作同一个队列,且加锁保护所有共享资源访问,修改逻辑如下:
- 将
Test函数的队列参数改为引用类型,避免多份拷贝,保证所有线程操作同一个队列实例 - 新增
std::mutex互斥锁,所有队列操作、标准输出操作都放在锁的保护范围内,保证同一时间只有一个线程访问共享资源 - 队列判空逻辑要放在锁内执行,避免判空后加锁前队列被其他线程清空的问题
修改后的可运行代码如下:
#include <iostream> #include <queue> #include <thread> #include <mutex> #include <vector> using namespace std; void Test(queue<string>& queue, std::mutex& mtx){ while (true) { // 加锁保护所有队列操作和输出 std::lock_guard<std::mutex> lock(mtx); // 队列空就退出线程 if (queue.empty()) { break; } string proxy = queue.front(); cout << proxy << "\n"; queue.pop(); } } int main() { queue<string> queue; std::mutex mtx; queue.push("101.132.186.39:9090"); queue.push("95.85.24.83:8118"); queue.push("185.211.193.162:8080"); queue.push("87.106.37.89:8888"); queue.push("159.203.61.169:8080"); std::vector<std::thread> ThreadVector; for (int i = 0; i <= 10; i++){ // 显式捕获队列和互斥锁的引用 ThreadVector.emplace_back([&queue, &mtx]() { Test(queue, mtx); }); } for (auto& t : ThreadVector){ t.join(); } ThreadVector.clear(); return 0; }
内容的提问来源于stack exchange,提问作者GoekhanDev
相关产品推荐
相关产品推荐

