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

C++ 基于mutex与condition_variable的生产者消费者死锁问题求助

死锁根因

当前代码死锁的核心原因是所有餐品生产、消费完成后,剩余消费者线程会永久阻塞:

  • 生产者生产完numero_pratos份餐品后直接退出,不会再发送任何通知
  • 仍在等待缓冲区有新餐品的消费者永远等不到唤醒信号,陷入永久等待

另外还有两个隐藏问题:

  1. 生产、消费的耗时sleep操作放在了锁持有区间,所有线程被迫串行执行,完全没有并发效果
  2. 消费退出逻辑只判断了已消费数量,没有结合生产完成状态,逻辑不严谨

修复方案

  • 新增全局生产完成标记,生产者结束生产后更新标记并唤醒所有消费者
  • 消费者等待条件新增生产完成状态判断,确认无新餐品且缓冲区为空时直接退出
  • 把生产、消费的耗时sleep移到锁外,符合真实业务逻辑同时提升并发效率
  • 消费完成后调用notify_all保证等待的生产者能被正确唤醒

修复后完整代码

#include <iostream>
#include <vector>
#include <chrono>
#include <thread>
#include <mutex>
#include <deque>
#include <condition_variable>

std::mutex semaforo;
std::condition_variable notifica;
std::deque<int> buffer;
const unsigned int capacidade_buffer = 10;
const unsigned int numero_pratos = 25;
bool production_finished = false; // 新增生产完成标记

void produtor()
{
    unsigned int contador_pratos_produzidos = 0;
    while (contador_pratos_produzidos < numero_pratos)
    {
        // 生产耗时放在锁外,不阻塞其他线程
        std::this_thread::sleep_for(std::chrono::microseconds(50));
        
        std::unique_lock<std::mutex> locker(semaforo);
        notifica.wait(locker, []
                      { return buffer.size() < capacidade_buffer; });
        
        buffer.push_back(contador_pratos_produzidos);
        contador_pratos_produzidos++;
        
        locker.unlock();
        notifica.notify_all();
    }
    // 生产全部完成,更新标记并唤醒所有消费者
    {
        std::lock_guard<std::mutex> locker(semaforo);
        production_finished = true;
    }
    notifica.notify_all();
}

void consumidor(int ID, std::vector<int> &consumido)
{
    unsigned int contador_pratos_consumidos = 0;
    while (true)
    {
        std::unique_lock<std::mutex> locker(semaforo);
        // 等待条件新增生产完成判断
        notifica.wait(locker, []
                      { return buffer.size() > 0 || production_finished; });
        
        // 生产结束且缓冲区为空,直接退出
        if (production_finished && buffer.empty()) {
            locker.unlock();
            break;
        }
        // 缓冲区有餐品,执行消费
        buffer.pop_front();
        contador_pratos_consumidos++;
        consumido[ID]++;
        
        locker.unlock();
        notifica.notify_all();
        
        // 配送耗时放在锁外,不阻塞其他线程
        std::this_thread::sleep_for(std::chrono::microseconds(15));
    }
}

int main()
{
    std::vector<int> consumido(6, 0);
    std::vector<std::thread> consumidores;
    for (int k = 0; k < 6; k++)
    {
        consumidores.push_back(std::thread(consumidor, k, std::ref(consumido)));
    }

    std::thread p1(produtor);

    for (auto &k : consumidores)
    {
        k.join();
    }
    p1.join();

    int mais_ocioso = 200, menos_ocioso = 0, mais, menos;
    for (int k = 0; k < 6; k++)
    {
        std::cout << "Garcon " << k + 1 << " entregou " << consumido[k] << " pratos\n";
        if (consumido[k] > menos_ocioso)
        {
            menos = k + 1;
            menos_ocioso = consumido[k];
        }
        if (consumido[k] < mais_ocioso)
        {
            mais = k + 1;
            mais_ocioso = consumido[k];
        }
    }
    std::cout << "\nO mais ocioso foi o garcon " << mais << " e o menos ocioso foi o garcon " << menos << "\n";
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:24:02