C++实现生产者消费者模型

C++实现生产者消费者模型


文章目录

  • C++实现生产者消费者模型
  • 一、生产者消费模型是什么?
  • 二、C++代码实现
    • 1.引入库和全局变量
    • 2.生产者模块
    • 3.消费者模块
  • 三、完整代码及测试结果


一、生产者消费模型是什么?

生产者-消费者模型是一种用于解决多线程同步问题的经典设计模式,常见于缓冲区管理、任务调度等场景。该模型的核心是两个角色:生产者和消费者。通过共享缓冲区(通常是队列)进行协作。

二、C++代码实现

1.引入库和全局变量

#include <atomic>                    // 用于原子操作(如无锁递增),防止数据竞争
#include <condition_variable>        // 条件变量,用于线程间的等待与通知机制
#include <iostream>                  // 用于输入输出流操作(例如打印调试信息)
#include <mutex>                     // 互斥锁,用于保护临界区,防止多个线程同时访问共享资源
#include <queue>                     // 队列容器,用于存储生产者产生的数据
#include <thread>                    // 用于创建和管理线程
std::mutex mtx;                       // 互斥锁,保护对共享队列的并发访问
std::condition_variable pro;          // 条件变量,生产者在缓冲区满时等待
std::condition_variable con;          // 条件变量,消费者在缓冲区空时等待
std::queue<int> q;                    // 共享队列,用于存储生产者生成的数据
const int size = 10;                  // 队列的最大容量(缓冲区大小)
bool done = false;                    // 控制线程退出的标志变量
std::atomic<int> i(0);                // 原子变量,用于保证线程安全的产品编号生成

2.生产者模块

void product() {
    while (!done) {  // 在没有结束标志时持续生产
        int item;    // 用于存储生成的产品编号
        {
            // 加锁,确保对共享资源(队列)的访问是线程安全的
            std::unique_lock<std::mutex> lck(mtx);

            // 当队列满时,生产者等待,直到队列有空间或程序结束
            pro.wait(lck, []{ return q.size() < size || done; });

            if (done) break;  // 如果设置了退出标志,则跳出循环

            // 生成产品编号,使用原子递增保证线程安全
            item = ++i;

            // 将产品放入队列
            q.push(item);

            // 输出产品编号,方便观察生产情况
            std::cout << "Produced: " << item << std::endl;
        }

        // 通知消费者有新产品可以消费
        con.notify_one();
    }
}

3.消费者模块

void consume() {
    while (!done) {  // 在没有结束标志时持续消费
        int item;    // 用于存储从队列中取出的产品
        {
            // 加锁,确保对共享资源(队列)的访问是线程安全的
            std::unique_lock<std::mutex> lck(mtx);

            // 当队列为空时,消费者等待,直到队列有数据或程序结束
            con.wait(lck, []{ return q.size() > 0 || done; });

            // 如果设置了退出标志,且队列为空,跳出循环
            if (done && q.empty()) break;

            // 从队列中取出产品
            item = q.front();
            q.pop();

            // 输出产品编号,方便观察消费情况
            std::cout << "Consumed: " << item << std::endl;
        }

        // 通知生产者有空间可以继续生产
        pro.notify_one();
    }
}

三、完整代码及测试结果

#include <atomic>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>

std::mutex mtx;
std::condition_variable pro;
std::condition_variable con;
std::queue<int> q;
const int size = 10;
bool done = false;
std::atomic<int> i(0);

void product() {
    while (!done) {
        int item;
        {
            std::unique_lock<std::mutex> lck(mtx);
            pro.wait(lck, []{ return q.size() < size || done; });
            if (done) break;

            item = ++i;
            q.push(item);
            std::cout << "Produced: " << item << std::endl;
        }
        con.notify_one();
    }
}

void consume() {
    while (!done) {
        int item;
        {
            std::unique_lock<std::mutex> lck(mtx);
            con.wait(lck, []{ return q.size() > 0 || done; });
            if (done && q.empty()) break;

            item = q.front();
            q.pop();
            std::cout << "Consumed: " << item << std::endl;
        }
        pro.notify_one();
    }
}

int main() {
    // 创建两个生产者线程
    std::thread p1(product);
    std::thread p2(product);

    // 创建两个消费者线程
    std::thread c1(consume);
    std::thread c2(consume);

    // 让主线程休眠 2 秒,模拟生产和消费过程
    std::this_thread::sleep_for(std::chrono::seconds(2));

    // 设置退出标志,通知生产者和消费者结束
    done = true;

    // 唤醒所有等待的线程,以便它们检查退出标志并退出
    pro.notify_all();
    con.notify_all();

    // 等待所有线程结束
    p1.join();
    p2.join();
    c1.join();
    c2.join();
    
    return 0;
}

测试结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值