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

C++多线程操作queue时所有线程获取队列同一条数据问题求助

问题原因分析
  • 队列值传递产生多份独立副本:你定义的Test函数参数为值类型queue<string> queue,每个线程调用Test时都会完整拷贝主函数中的原队列,所有线程操作的是自己本地的队列副本,执行pop操作只会清空自己本地的副本,不会影响其他线程的队列数据,因此每个线程都会遍历输出全部队列元素,出现重复取到同一条数据的现象。
  • 无同步机制导致线程安全问题:即使将参数改为引用传递让所有线程操作同一个队列,std::queue本身也不具备线程安全特性,多线程同时执行empty()、front()、pop()操作会触发数据竞争,属于C++标准规定的未定义行为,依然会出现重复取数、程序异常崩溃等问题。
  • 标准输出无同步保护:std::cout本身不是线程安全的,多线程同时输出会导致内容乱序、字符拼接错误等异常。
解决方法

需要修改代码实现所有线程操作同一个队列,且加锁保护所有共享资源访问,修改逻辑如下:

  1. 将Test函数的队列参数改为引用类型,避免多份拷贝,保证所有线程操作同一个队列实例
  2. 新增std::mutex互斥锁,所有队列操作、标准输出操作都放在锁的保护范围内,保证同一时间只有一个线程访问共享资源
  3. 队列判空逻辑要放在锁内执行,避免判空后加锁前队列被其他线程清空的问题

修改后的可运行代码如下:

#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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 10:09:03