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

C++中用condition_variable实现多生产者消费者遇阻塞问题求助

生产者消费者模型阻塞问题排查

问题描述

尝试用C++的std::condition_variable实现生产者消费者模型,使用ready(消费者等待标记)和processed(生产者等待标记)两个布尔变量协调线程,但运行后生产者很快出现阻塞。日志显示消费者完成数据处理后,没有成功唤醒生产者继续生产。

生产者与消费者代码

void producer() {
  bool shouldQuit = false;
  while (!shouldQuit) {
    std::unique_lock lk(md);
    std::cout << "p" << threadid << " waiting" << std::endl;
    cv.wait(lk, [] { return processed; });
    processed = false;
    std::cout << "p" << threadid << " finished waiting" << std::endl;
    if (d < 10) {
      data = "p" + std::to_string(threadid) + " " + std::to_string(d);
      std::cout << data << std::endl;
      d++;
      std::cout << "p" << threadid << " unlocking" << std::endl;
      ready = true;
      lk.unlock();
      std::cout << "p" << threadid << " unlocked" << std::endl;
      cv.notify_one();
    } else {
      shouldQuit = true;
    }
  }
}

void consumer() {
  bool shouldQuit = false;
  while (!shouldQuit) {
    std::unique_lock lk(md);
    std::cout << "c" << threadid << " waiting" << std::endl;
    cv.wait(lk, [] { return ready; });
    ready = false;
    std::cout << "c" << threadid << " finished waiting" << std::endl;
    if (data.empty()) {
      shouldQuit = true;
    } else {
      std::cout << "c" << threadid << " < " << data << std::endl;
      processed = true;
    }
    std::cout << "c" << threadid << " unlocking" << std::endl;
    lk.unlock();
    cv.notify_one();
    std::cout << "c" << threadid << " unlocked" << std::endl;
  }
}

运行日志

prod 0
p0 waiting
p0 finished waiting
p0 0
p0 unlocking
p0 unlocked
p0 waiting
prod 1
p1 waiting
cons 2
c2 waiting
c2 finished waiting
c2 < p0 0
c2 unlocking
c2 unlocked
c2 waiting
p0 finished waiting
p0 1
p0 unlocking
p0 unlocked
p0 waiting
cons 3
c3 waiting
c3 finished waiting
c3 < p0 1
c3 unlocking <--- this should unblock any producer to produce more, but it doesn't :(
c3 unlocked
c3 waiting

问题排查提示

  • 条件变量复用导致唤醒错误线程
    当前生产者和消费者共用同一个std::condition_variable实例。调用notify_one()时,系统会从等待该变量的线程中随机唤醒一个——日志场景中,消费者c3的通知可能唤醒了另一个等待的消费者c2,而非生产者。被唤醒的c2检查ready为false后会再次进入等待,导致生产者持续阻塞。
    修复:为生产者和消费者分别创建独立的条件变量(如cv_prod和cv_cons),消费者处理完成后调用cv_prod.notify_one()唤醒生产者,生产者生产完成后调用cv_cons.notify_one()唤醒消费者。

  • 调整通知时机到互斥锁释放前
    建议在保持互斥锁锁定的状态下调用notify,避免信号丢失风险。比如消费者可以在设置processed = true后立即调用cv_prod.notify_one(),再释放锁,确保生产者被唤醒时能看到正确的状态。

  • 严格保证共享变量的线程安全
    所有共享变量(processed、ready、data、d)的读写操作必须在互斥锁保护范围内,避免数据竞争导致的状态混乱。当前代码中这部分操作符合规范,需继续保持。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 22:13:15