首页 > 编程语言 >c++编写生产者消费者模型

c++编写生产者消费者模型

时间:2024-08-04 19:59:17浏览次数:15  
标签:std 生产者 lock c++ queue 队列 cond 编写 size

直接上代码啦:

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

// 定义一个同步的队列类
class SyncQueue {
public:
    SyncQueue(size_t capacity) : max_capacity(capacity) {}

    void push(int value) {
        std::unique_lock<std::mutex> lock(mtx);
        // 等待直到队列有足够空间
        space_cond.wait(lock, [this] { return queue.size() < max_capacity; });
        queue.push(value);
        lock.unlock();
        data_cond.notify_one(); // 通知等待的线程数据已经可用
    }

    int pop() {
        std::unique_lock<std::mutex> lock(mtx);
        data_cond.wait(lock, [this] { return !queue.empty(); }); // 等待直到队列非空
        int value = queue.front();
        queue.pop();
        lock.unlock();
        space_cond.notify_one(); // 通知等待的线程现在有空间了
        return value;
    }

    size_t size() const {
        std::lock_guard<std::mutex> lock(mtx);
        return queue.size();
    }

private:
    std::queue<int> queue;
    size_t max_capacity;
    std::mutex mtx;
    std::condition_variable data_cond;
    std::condition_variable space_cond;
};

void producer(SyncQueue& q) {
    for (int i = 0; i < 10; ++i) {
        std::cout << "Producing: " << i << std::endl;
        q.push(i);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void consumer(SyncQueue& q) {
    for (int i = 0; i < 10; ++i) {
        int value = q.pop();
        std::cout << "Consuming: " << value << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
    }
}

int main() {
    SyncQueue q(5); // 设置队列的最大容量为5

    std::thread t1(producer, std::ref(q));
    std::thread t2(consumer, std::ref(q));

    t1.join();
    t2.join();

    return 0;
}

在这个版本中,我们增加了以下几点:

  • SyncQueue构造函数接收一个参数capacity,表示队列的最大容量。
  • push方法中,我们使用space_cond条件变量来等待直到队列中有足够的空间可以插入新元素。
  • pop方法中,我们同样使用data_cond条件变量来等待直到队列非空。
  • 我们还添加了一个size成员函数,用于返回当前队列中的元素数量,这可以用来进行测试或调试。

这样,当队列已满时,生产者线程将会阻塞,等待消费者线程消费数据以腾出空间。同样,当队列为空时,消费者线程也会阻塞,等待生产者线程填入数据。

标签:std,生产者,lock,c++,queue,队列,cond,编写,size
From: https://blog.csdn.net/semicolon_hello/article/details/140910740

相关文章

  • windows C++-通过 C++/WinRT 使用 API(三)
    统一构造在C++/WinRT版本2.0及更高版本中,有一种优化的构造形式可供你使用,它被称作“统一构造”(请参见C++/WinRT2.0中的新增功能和更改)。若要使用统一构造而不是winrt::make,你需要一个激活工厂。要生成激活工厂,一种好的方式是向IDL添加构造函数。//MainPage.idl......
  • windows C++-通过 C++/WinRT 使用 API(二)
    延迟初始化在C++/WinRT中,每个类型都有一个特殊的C++/WinRTstd::nullptr_t构造函数。除了该构造函数,所有其他类型的构造函数(包括默认的构造函数)都会导致系统创建一个支持的Windows运行时对象,并为你提供它的智能指针。因此,该规则适用于使用默认构造函数的任何地方,例如......
  • C++3级
    虚拟星辰大家好,我是新人,这是我的第一个博客,6月29日的3级认证T1题目大致是这样的:小杨发明了一套密码系统,具体来说,他把字母的顺序向后移了N位。比如说,原来的字母顺序是:ABCDEFGHIJKLMNOPQRSTUVWXYZ当N为1时,字母顺序变为:BCDEFGHIJKLMNOPQRSTUVWXYZA当N为2时,字母顺序变为:CDEF......
  • C++入门
    目录命名空间IO流缺省参数函数重载为什么C语言不支持重载而C++支持重载?引用引用特性:常引用使用场景引用和指针的区别内联函数的定义以及注意auto关键字自动类型推断基于范围的for循环命名空间C语言中会有命名冲突,C++为了解决这个问题增加了namespace(命名空间)......
  • 如何处理“内部C++对象(某些对象)已删除”?
    当我关闭具有记录器的窗口然后重新打开该窗口时,我收到“RuntimeError:内部C++对象(PySide6.QtWidgets.QPlainTextEdit)已删除。”(我根据这篇文章制作了记录器:在pyqt中显示日志的最佳方式?)。当我从LoggerWindow的closeEvent中删除“self.deleteLater()”时,我没......
  • 程序编写规范
    ......
  • C++ 返回值类型推导
    C++返回值类型推导前言C++中获取函数签名可以很简单地用decltype(函数名)来获得,但是这样无法直接提取出返回值类型。有时我们需要获取函数或可调用对象的返回值类型,以便进行后续的操作,在泛型编程中很常用,特别是当不同的参数集的结果类型不同时。头文件<type_traits>:C......
  • 【C++核心篇】—— C++面向对象编程:封装相关语法使用和注意事项详解(全网最详细!!!)
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、封装(类)1.封装的使用(类和对象)2.对象的初始化和清理2.1构造函数2.2析构函数2.3构造函数的分类及调用3.深拷贝与浅拷贝4.C++对象模型和this指针5.友元6.运算符重载前言在本篇......
  • 【C++基础篇】—— 面向对象编程前的准备(内存分区,引用、函数重载)
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、内存分区模型1.C++内存分区2.new操作符二、引用三、函数重载1.函数基本使用2.函数重载前言在本篇文章中,主要是对C++的基础语法进行回顾学习,回顾学习C++的基本语法规则、数据类型......
  • CPlusPlus - #034 C++ 中的零拷贝技术
    文章目录C++中的零拷贝技术探析1前言2.1使用mmap实现零拷贝2.2使用sendfile实现零拷贝2.3优缺点和适用场合2.3.1mmap2.3.1.1优点2.3.1.2缺点2.3.1.3适用场景2.3.2sendfile2.3.2.1优点2.3.2.2缺点2.3.2.3适用场景2.4总结......