生产者消费者模型(多线程工作)
目录
1.模型前提
2.阻塞队列(消费场所)
3. 实验
4.有关效率
1.模型前提
以单生产者对单消费者为例子:
前提一:有一个缓冲区作为消费场所。
前提二:有两种功能不同的线程分别具有消费与生产的能力。
前提三:生产者与生产者之间有互斥的关系,消费者与消费者之间有互斥的关系,生产者与消费者之间同时具有互斥与同步的关系。
2.阻塞队列(消费场所)
阻塞队列与普通队列最大的不同是:当队列满时生产者不能继续生产,当队列空时消费者不能继续消费。
3. 实验
来展示一份多线程工作遵循生产者消费者模型的代码。
部分1:设置消费的模板(task.hpp)
#pragma once#include <iostream>
#include <functional>typedef std::function<int(int, int)> func_t;//c++11特性打包器class Task
{public:Task(){}Task(int x, int y, func_t func):x_(x), y_(y), func_(func){}int operator ()() //仿函数{return func_(x_, y_);}
public:int x_;int y_;func_t func_;
};
部分2:采用raii的方式设置锁的处置方式(lockGuard.hpp)
#pragma once#include <iostream>
#include <pthread.h>class Mutex
{
public:Mutex(pthread_mutex_t *mtx):pmtx_(mtx){}void lock() {std::cout << "要进行加锁" << std::endl;pthread_mutex_lock(pmtx_);}void unlock(){std::cout << "要进行解锁" << std::endl;pthread_mutex_unlock(pmtx_);}~Mutex(){}
private:pthread_mutex_t *pmtx_;
};// RAII风格的加锁方式
class lockGuard
{
public://构造时加锁//析构时解锁lockGuard(pthread_mutex_t *mtx):mtx_(mtx){mtx_.lock();}~lockGuard(){mtx_.unlock();}
private:Mutex mtx_; //锁
};
这里解释一下为什么要加锁,因为要维护前提三,也就是要维护互斥的关系。
部分3:阻塞队列这个数据结构
#pragma once#include <iostream>
#include <queue>
#include <mutex>
#include <pthread.h>
#include "lockGuard.hpp"const int gDefaultCap = 5;template <class T>
class BlockQueue
{
private://判断队列的空与满bool isQueueEmpty(){return bq_.size() == 0;}bool isQueueFull(){return bq_.size() == capacity_;}public:BlockQueue(int capacity = gDefaultCap) : capacity_(capacity){pthread_mutex_init(&mtx_, nullptr);pthread_cond_init(&Empty_, nullptr);pthread_cond_init(&Full_, nullptr);}void push(const T &in) // 生产者{lockGuard lockgrard(&mtx_); // 自动调用构造函数//不停的检查直到队列非满while (isQueueFull())pthread_cond_wait(&Full_, &mtx_); //等待时会自动解锁,消费者可以消费bq_.push(in); //非满时可以插入任务(数据)pthread_cond_signal(&Empty_); //既然插入的数据,那么队列为空这个条件变量就可以解除了。} // 自动调用lockgrard 析构函数void pop(T *out){lockGuard lockguard(&mtx_);while (isQueueEmpty())pthread_cond_wait(&Empty_, &mtx_);*out = bq_.front();bq_.pop();pthread_cond_signal(&Full_);}~BlockQueue(){pthread_mutex_destroy(&mtx_);pthread_cond_destroy(&Empty_);pthread_cond_destroy(&Full_);}private:std::queue<T> bq_; // 阻塞队列int capacity_; // 容量上限pthread_mutex_t mtx_; // 通过互斥锁保证队列安全pthread_cond_t Empty_; // 用它来表示bq 是否空的条件pthread_cond_t Full_; // 用它来表示bq 是否满的条件
};
部分4:主程序部分,创建线程。
#include "BlockQueue.hpp"
#include "Task.hpp"#include <pthread.h>
#include <unistd.h>
#include <ctime>int myAdd(int x, int y) //设置了消费方式
{return x + y;
}void* consumer(void *args) //消费者
{BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;while(true){// 获取任务Task t;bqueue->pop(&t);// 完成任务std::cout << pthread_self() <<" consumer: "<< t.x_ << "+" << t.y_ << "=" << t() << std::endl;// sleep(1);}return nullptr;
}void* productor(void *args) //生产者
{BlockQueue<Task> *bqueue = (BlockQueue<Task> *)args;while(true){// 制作任务 -- 不一定是从生产者来的int x = rand()%10 + 1;usleep(rand()%1000);int y = rand()%5 + 1;Task t(x, y, myAdd);// 生产任务bqueue->push(t);// 输出消息std::cout <<pthread_self() <<" productor: "<< t.x_ << "+" << t.y_ << "=?" << std::endl;sleep(1);}return nullptr;
}int main()
{//生成随机数种子srand((uint64_t)time(nullptr) ^ getpid() ^ 0x32457);BlockQueue<Task> *bqueue = new BlockQueue<Task>();pthread_t c[2],p[2];//创建线程pthread_create(c, nullptr, consumer, bqueue);pthread_create(c + 1, nullptr, consumer, bqueue);pthread_create(p, nullptr, productor, bqueue);pthread_create(p + 1, nullptr, productor, bqueue);//销毁线程pthread_join(c[0], nullptr);pthread_join(c[1], nullptr);pthread_join(p[0], nullptr);pthread_join(p[1], nullptr);delete bqueue;return 0;
}
结果:
没有问题,生产者生产一次消费者就消费一次,并且在这之间存在了加解锁的过程。
4.有关效率
有人可能会疑问“明明还是加锁了,那不是没有提升效率嘛”。
由于生产者与消费之间存在消费场所,就可以做到生产者生产的同时消费者从消费场所拿走数据进行消费。因此提升的不是生产者与消费者之间传递数据的速度,而是提升了生产者生产数据的效率与消费者消费数据的效率。
相关文章:

生产者消费者模型(多线程工作)
目录 1.模型前提 2.阻塞队列(消费场所) 3. 实验 4.有关效率 1.模型前提 以单生产者对单消费者为例子: 前提一:有一个缓冲区作为消费场所。 前提二:有两种功能不同的线程分别具有消费与生产的能力。 前提三&…...
InnoDB锁
1、共享排他锁 Shared and Exclusive Locks--共享锁(SLock),允许持有该锁的事务读取一行数据--排它锁(XLock),允许持有该锁的事务删除或者更新一行数据特性:--行级锁--如果一个事务持有当前行的…...

Java Stream、File、IO 超详细整理,适合新手入门
目录 Java Stream Java File Java IO Java Stream Java Stream 是 Java 8 中引入的一种新的抽象数据类型,它允许开发人员使用函数式编程的方式来处理集合数据。 使用 Java Stream 可以方便地进行过滤、映射、排序和聚合等操作。下面是一个简单的示例:…...
华为OD机试真题Python实现【寻找密码】真题+解题思路+代码(20222023)
寻找密码 题目 小王在进行游戏大闯关,有一个关卡需要输入一个密码才能通过,密码获得的条件如下: 在一个密码本中,每一页都有一个由 26 个小写字母组成的若干位密码, 从它的末尾开始依次去掉一位得到的新密码也在密码本中存在。 请输出符合要求的密码,如果由多个符合要求…...
springboot和springframework版本依赖关系
springboot和springframework版本依赖关系 springboot版本springframework版本发布时间1.0.x1.0.0.RELEASE4.0.3.RELEASE2014.041.0.1.RELEASE4.0.3.RELEASE2014.041.0.2.RELEASE4.0.3.RELEASE2014.041.1.x1.1.0.RELEASE4.0.5.RELEASE2014.061.1.1.RELEASE4.0.5.RELEASE2014.0…...

Java-多线程-增强篇-锁 强化 第一篇
今天我们来学一下锁 会持续保持更新 欢迎追更哈 Java - 多线程 - 锁和提升 第1篇 首先强调一点:Java多线程的锁都是基于对象的,Java中的每一个对象都可以作为一个锁。同时,类锁也是对象锁,类是Class对象 Java8锁 核心思想 关键…...
Java static+private实现单例模式
1. 单例模式介绍 在Java中单例设计模式准确来说是,类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。 2. 实现思路 如果我们要让类在一个虚…...

华为OD机试 - 查找充电设备组合(Python)【2023-Q1 新题】
华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 查找充电设备组合…...

Authing 入选德勤“中国明日之星”企业榜单
近日,德勤发布“德勤中国明日之星”榜单,该项目致力于发掘和表彰蓬勃成长、持续创新、积极承担社会责任的卓越企业。该榜单1995 年创立至今,被业界誉为“全球高成长企业的标杆”。Authing 凭借在 IDaaS(身份云) 领域突…...
单片机嵌入式操作系统内核
1、前后台系统,协作式内核系统,与占先式内核系统,有什么不同呢? 记得在 21IC 上看过这样的比喻, 你(小工)在用厕所,经理在外面排第一,老板在外面排第二。 如果是前后台,不管是谁,都…...

C语言——柔性数组
目录0. 前言1. 思维导图2. 柔性数组的特点3. 柔性数组的使用4. 柔性数组的优势5. 结语0. 前言 柔性数组是在C99标准时引入: 结构中的最后一个元素允许是未知大小的数组,这就叫柔性数组成员。 代码示例: typedef struct flexible_arr {int a…...
web人脸登录
1,需要腾讯人脸第三方 腾讯人脸第三方申请步骤 2,相关表结构设计 create database faceDB;use faceDB; -- 人脸表 create table face( fid int primary key auto_increment COMMENT 主键, face_base longtext COMMENT 图片数据 base_64编码, create_tim…...
C++数字
目录 一、什么是数字 二、定义数字 三、数学运算 四、随机数 一、什么是数字 通常,当我们需要用到数字时,我们会使用原始的数据类型,如 int、short、long、float 和 double 等等。这些用于数字的数据类型,其可能的值和数值范围…...

【python】用plotly绘制正二十面体
文章目录顶点棱实现正二十面体plotly 的 Python 软件包是一个开源的代码库,它基于 plot.js,而后者基于 d3.js。我们实际使用的则是一个对 plotly 进行封装的库,名叫 cufflinks,能让你更方便地使用 plotly 和 Pandas 数据表协同工作…...

[Datawhale][CS224W]图机器学习(五)
这里写目录标题一、Deepwalk1.1 预备知识1.2 Deepwalk介绍1.3 Embedding1.4 word2Vec 词向量,词嵌入1.5 random Walk随机游走1.6 DeepWalk 核心代码Random WalkWord2vecDeepWalk应用1.7 DeepWalk优缺点二、Node2Vec2.1 图嵌入2.2 Node2Vec优化目标顶点序列采样策略2…...

Windows部署Jar包的三种方式
文章目录1、cmd命令启动2、bat脚本启动2.1 启动jar包2.2 关闭服务3、使用WinSW3.1 重命名3.2 xml配置3.3 安装服务3.4 卸载服务3.5 启动和停止服务1、cmd命令启动 这种方式比较简单,但是窗口关闭后服务也就被杀死了,命令如下 java -jar xxx.jar2、bat脚…...
【图像分类】卷积神经网络之AlexNet网络模型结构详解
写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 1. 前言 LeNet5网络模型提出之后,卷积神经网络在很长一段时间都没有长足的发展,主要有以下两个原因: 1.1 训…...

学习动漫插画的网络班排行榜
很多小伙伴不知道动漫插画培训机构哪个好,找不到靠谱的插画班,今天给大家整理了国内动漫插画培训机构排名! 一:动漫插画培训机构排名 1、轻微课(五颗星) 主打课程有日系插画、游戏原画、古风插画、动漫漫画…...

SpringCloud第五讲 Nacos注册中心-服务注册到Nacos
1.引入依赖: 在父工程中添加spring-cloud-alibaba的管理依赖 <!-- Nacos的管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version…...

IP地理位置定位技术原理是什么
IP地理位置定位技术的原理是基于IP地址的网络通信原理和基础上的。它利用IP地址所包含的一些信息,如网络前缀和地址段,以及ISP的IP地址归属地数据库,来推测IP地址所对应的地理位置。具体来说,IP地址是由32位二进制数字组成的&…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...