首页 > 编程语言 >C++实现一个简单的生产者-消费者队列

C++实现一个简单的生产者-消费者队列

时间:2023-04-27 23:12:03浏览次数:33  
标签:std 队列 ProducerConsumerQueue C++ queue 生产者 int mutex curSize

本文的代码都是ChatGPT生成,我只是做了微小的调整和整合,AI提示词如下:

设计一个C++类,支持生产者-消费者模型,可以通过size函数获取剩余数量

可能第一次生成的不一定合适,多刷新几次。
生成的ProducerConsumerQueue.h代码如下:

#ifndef PRODUCER_CONSUMER_QUEUE_H
#define PRODUCER_CONSUMER_QUEUE_H

#include <queue>
#include <mutex>
#include <condition_variable>

template<typename T>
class ProducerConsumerQueue {
public:
    ProducerConsumerQueue(int size) : m_maxSize(size), m_curSize(0) {}

    void push(T& val) {
        std::unique_lock<std::mutex> lock(m_mutex);
        while (m_curSize >= m_maxSize) {
            m_notFull.wait(lock);
        }
        m_queue.push(val);
        ++m_curSize;
        m_notEmpty.notify_one();
    }

    T pop() {
        std::unique_lock<std::mutex> lock(m_mutex);
        while (m_curSize <= 0) {
            m_notEmpty.wait(lock);
        }
        T val = m_queue.front();
        m_queue.pop();
        --m_curSize;
        m_notFull.notify_one();
        return val;
    }

    int size() {
        std::unique_lock<std::mutex> lock(m_mutex);
        return m_curSize;
    }

private:
    std::queue<T> m_queue;
    int m_maxSize;
    int m_curSize;
    std::mutex m_mutex;
    std::condition_variable m_notEmpty;
    std::condition_variable m_notFull;
};

#endif //PRODUCER_CONSUMER_QUEUE_H

在上面的代码中,我们定义了一个ProducerConsumerQueue类:

  • ProducerConsumerQueue类有最大容量和当前容量两个属性,使用std::queue<int>存储数据,使用std::mutex保证线程安全,使用std::condition_variable实现线程同步。
  • 在push函数中,如果当前容量已满,等待消费者消费;否则插入数据,当前容量加1,通知消费者
  • 在pop函数中,如果当前容量为0,等待生产者生产;否则取出数据,当前容量减1,通知生产者
  • 在size函数中,使用std::unique_lockstd::mutex保证线程安全,获取当前容量并返回。

测试示例代码如下:

#include <iostream>
#include "ProducerConsumerQueue.h"

int main() {
    ProducerConsumerQueue<int> queue(2);

    // 生产者线程
    std::thread producer([&queue] {
        for (int i = 0; i < 10; ++i) {
            queue.push(i);
        }
        });

    // 消费者线程
    std::thread consumer([&queue] {
        for (int i = 0; i < 10; ++i) {
            int value = queue.pop();
            std::cout << "Consumed " << value << std::endl;
            std::cout << queue.size() << std::endl;
        }
        });

    producer.join();
    consumer.join();
}

标签:std,队列,ProducerConsumerQueue,C++,queue,生产者,int,mutex,curSize
From: https://www.cnblogs.com/timefiles/p/17360496.html

相关文章

  • C++黑马程序员——P143-146. 文件操作
    P143.C++文件操作——文本文件——写文件P144.C++文件操作——文本文件——读文件P143.写文件   示例:1#include<iostream>2#include<string>3usingnamespacestd;4#include<fstream>56//文本文件写文件78voidtes......
  • C/C++会员管理系统[2023-04-27]
    C/C++会员管理系统[2023-04-27]综合设计实例四课题名称:会员管理系统I、题目的目的和要求(2-3人组)随着社会的进步,人们生活水平的提高,各种各样的会员应运而生。各种便民服务的地方为了提高服务粘性,留住顾客往往采用会员制,例如便利店、健身房,生鲜超市、美容美发店等等不一而足......
  • C++第四章课后练习题4-22
    1#include<iostream>2usingnamespacestd;3enumweekday{sunday,monday,tuesday,wednesday,thursday,friday,saturday4};5intmain()6{7inti;8weekdayd=thursday;9cout<<"d="<<d<<endl;10......
  • c++打卡练习(18)
    猜牌术魔术师利用一副牌中的13张黑桃,预先将它们排好后迭在一起,并使牌面朝下。然后他对观众说:我不看牌,只要数数就可以猜到每张牌是什么,我大声数数,你们听,不信?你们就看,魔术师将最上面的那张牌数为1,把它翻过来正好是黑桃A,他将黑桃A放在桌子上,然后按顺序从上到下数手中的余牌,第二次......
  • c/c++程序中获取当前可执行文件所在的目录路径,使用跨平台的program_location
    c/c++程序中获取当前可执行文件所在的目录路径对于大型工程中,可执行文件中通过c/c++代码获取到当前路径,可以很大方便于工程后续的部署与运维工作。比如说根据当前的可执行文件路径获取到配置文件的路径,然后加载读取配置文件。有了这个能力就不用再在操作系统中配置环境变量来指......
  • C++
    狗的继承完成两个类,一个类Animal,表示动物类,有一个成员表示年龄。一个类Dog,继承自Animal,有一个新的数据成员表示颜色,合理设计这两个类,使得测试程序可以运行并得到正确的结果。 #include<iostream>usingnamespacestd;classAnimal{public:Animal(inty)......
  • c++引用折叠
    目录 一、引用折叠二、示例解析三、参考: 一、引用折叠   由于存在T&&这种万能引用类型,当它作为参数时,有可能被一个左值引用或右值引用的参数初始化,这是经过类型推导的T&&类型,相比右值引用(&&)会发生类型的变化,这种变化就称为引用折叠。1.所有右值引用折叠到右值引......
  • [C++11]左值、右值、左值引用、右值引用小结
     左值和右值左值:指表达式结束后依然存在的持久对象,可以取地址,具名变量或对象右值:表达式结束后就不再存在的临时对象,不可以取地址,没有名字。比如inta=b+c;,a就是一个左值,可以对a取地址,而b+c就是一个右值,对表达式b+c取地址会报错。C++11中右值又由两个概念组成:将亡值和纯......
  • C++ inline
    在C++中,inline关键字用于建议编译器将函数内联到调用它的地方。内联函数是一种优化技术,可以减少函数调用的开销。当一个函数被声明为内联时,编译器会尝试将函数的代码直接嵌入到每个调用该函数的地方,从而避免了函数调用时产生的额外开销,如保存寄存器、设置栈帧等。需要注意的是,inl......
  • 【C++】引用、引用初始化、引用折叠规则
     引用引用就好像存储数据的一块内存区域(变量)的一个名字,定义引用就好像声明了一个变量名并把它绑定到已存在的变量上,变量名附带属性(包括但不限于类型、存储期),变量名附带的属性由声明变量名时使用的声明指定符决定。需要注意的是,用于声明左值引用的&和用于声明右值引用的&&不......