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

C++生产者消费者模型异常排查:为何先填满缓冲区再消费?

问题分析与修复

你的代码核心问题是生产者和消费者在持有互斥锁的状态下执行sleep操作,导致锁被长时间占用,对方线程完全无法获取锁执行任务:

具体原因

  1. 生产者线程中,std::this_thread::sleep_for(std::chrono::seconds(1)); 写在unique_lock<mutex> lk(mtx);的作用域内——也就是持有锁的状态下休眠。这意味着生产者每生产一个数据后,会攥着锁睡1秒,这段时间消费者根本抢不到锁,没机会进入消费逻辑。
  2. 只有当生产者把缓冲区填满(达到容量n=2),cv.wait(lk,[&](){return q.size()<n;})的条件不满足,生产者才会释放锁进入等待状态,这时候消费者才能抢到锁开始消费。
  3. 同理,消费者拿到锁后也带着锁休眠,后续生产者也得等消费者休眠结束才能抢锁,完全失去了多线程并发的意义。

修复方案

把sleep操作移到互斥锁作用域之外,确保锁只在操作共享资源时持有,其余时间释放:

修复后的代码

#include <iostream>
#include <mutex>
#include <thread>
#include <queue>
#include <chrono>
using namespace std;

std::mutex mtx;
condition_variable cv;
queue<int> q;
int n=2;

int produceData() {
    int res=rand()%1000;
    cout<<"produce data:"<<res<<endl;
    return res;
}

void consumeData(int data) {
    cout<<"consume data:"<<data<<endl;
}

void producer(){
    while(true) {
        { // 用花括号缩小锁的作用域
            unique_lock<mutex> lk(mtx);
            cv.wait(lk,[&](){return q.size()<n;});
            q.push(produceData());
            cv.notify_one();
        } // 锁在这里自动释放
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void consumer() {
    while(true) {
        int data;
        {
            unique_lock<mutex> lk(mtx);
            cv.wait(lk,[&](){return q.size()>0;});
            data = q.front();
            q.pop();
            consumeData(data);
            cv.notify_one();
        } // 锁在这里自动释放
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
    return 0;
}

额外优化点

  • 把consumeData改成接收参数的形式,避免在消费时直接访问共享队列,减少锁内的操作时间。
  • 用花括号明确缩小锁的作用域,确保锁只在操作共享资源时持有,提升并发效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:11:07