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

C++队列与线程程序异常退出问题求助

C++多线程队列操作崩溃问题修复

实现目标

我想编写一个程序,在子线程中每秒向queue添加一个元素,主线程每两秒删除一个队列元素并显示队列的大小、队首和队尾数据。

原代码

#include <iostream>
#include <queue>
#include <thread>
#include <Windows.h>

using std::queue;
using std::cout;

void loadQueue(queue<int>& toLoad)
{
    for(int i = 0; i < 100; i++)
    {
        toLoad.push(i); 
        Sleep(1000);
    }
}

int main(void)
{
    queue<int>toLoad;
    std::thread(loadQueue, std::ref(toLoad));

    while(true)
    {
        cout << "SIZE OF QUEUE : " << toLoad.size() << '\n' << '\n'; 

        cout <<"FRONT :" << toLoad.front() << '\n' << '\n';

        cout <<"BACK : " << toLoad.back() << '\n';
        toLoad.pop();
        Sleep(2000);
    }
}

错误情况

程序启动后无任何输出,直接崩溃关闭。Visual Studio抛出的异常信息为:

Unhandled exception at 0x00007FF8B7C4A839 in Project1.exe: Microsoft C++ exception: std::underflow_error at memory location 0x0000004E7C1FE6D0.

问题分析

  1. 空队列非法访问:主线程启动后立即进入循环,调用toLoad.front()、toLoad.back()和toLoad.pop(),但子线程需要1秒才会添加第一个元素,此时队列为空,触发std::underflow_error异常导致崩溃。
  2. 线程安全问题:std::queue不是线程安全容器,子线程的push操作和主线程的size/front/back/pop操作同时进行会引发数据竞争,属于未定义行为。

修复方案

通过互斥锁和条件变量实现线程同步,确保主线程仅在队列非空时操作,同时保护队列的所有访问操作:

#include <iostream>
#include <queue>
#include <thread>
#include <Windows.h>
#include <mutex>
#include <condition_variable>

using std::queue;
using std::cout;
using std::mutex;
using std::condition_variable;
using std::unique_lock;

mutex queue_mutex;
condition_variable cv;

void loadQueue(queue<int>& toLoad)
{
    for(int i = 0; i < 100; i++)
    {
        {
            unique_lock<mutex> lock(queue_mutex);
            toLoad.push(i);
        }
        cv.notify_one(); // 通知主线程队列有新元素
        Sleep(1000);
    }
    cv.notify_one(); // 子线程结束前通知一次,避免主线程永久等待
}

int main(void)
{
    queue<int> toLoad;
    std::thread loader(loadQueue, std::ref(toLoad));
    loader.detach(); // 主线程是死循环,分离子线程

    while(true)
    {
        unique_lock<mutex> lock(queue_mutex);
        // 等待队列非空,避免虚假唤醒
        cv.wait(lock, [&toLoad](){ return !toLoad.empty(); });

        cout << "SIZE OF QUEUE : " << toLoad.size() << "\n\n"; 
        cout << "FRONT :" << toLoad.front() << "\n\n";
        cout << "BACK : " << toLoad.back() << "\n";
        toLoad.pop();
        
        lock.unlock(); // 解锁后再休眠,避免阻塞子线程的push操作
        Sleep(2000);
    }
}

修复说明

  • 互斥锁std::mutex:确保同一时间只有一个线程访问队列,杜绝数据竞争。
  • 条件变量std::condition_variable:让主线程在队列为空时进入等待状态,直到子线程添加元素后唤醒它,彻底解决空队列访问问题。
  • 解锁时机优化:在休眠前解锁互斥锁,让子线程可以继续向队列添加元素,提升并发效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:24:52