当前位置: 首页 > news >正文

生产者消费者模型(多线程工作)

目录

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.阻塞队列&#xff08;消费场所&#xff09; 3. 实验 4.有关效率 1.模型前提 以单生产者对单消费者为例子&#xff1a; 前提一&#xff1a;有一个缓冲区作为消费场所。 前提二&#xff1a;有两种功能不同的线程分别具有消费与生产的能力。 前提三&…...

InnoDB锁

1、共享排他锁 Shared and Exclusive Locks--共享锁&#xff08;SLock&#xff09;&#xff0c;允许持有该锁的事务读取一行数据--排它锁&#xff08;XLock&#xff09;&#xff0c;允许持有该锁的事务删除或者更新一行数据特性&#xff1a;--行级锁--如果一个事务持有当前行的…...

Java Stream、File、IO 超详细整理,适合新手入门

目录 Java Stream Java File Java IO Java Stream Java Stream 是 Java 8 中引入的一种新的抽象数据类型&#xff0c;它允许开发人员使用函数式编程的方式来处理集合数据。 使用 Java Stream 可以方便地进行过滤、映射、排序和聚合等操作。下面是一个简单的示例&#xff1a;…...

华为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篇 首先强调一点&#xff1a;Java多线程的锁都是基于对象的&#xff0c;Java中的每一个对象都可以作为一个锁。同时&#xff0c;类锁也是对象锁&#xff0c;类是Class对象 Java8锁 核心思想 关键…...

Java static+private实现单例模式

1. 单例模式介绍 在Java中单例设计模式准确来说是&#xff0c;类的单例设计模式&#xff0c;就是采取一定的方法保证在整个的软件系统中&#xff0c;对某个类只能存在一个对象实例&#xff0c;并且该类只提供一个取得其对象实例的方法。 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 入选德勤“中国明日之星”企业榜单

近日&#xff0c;德勤发布“德勤中国明日之星”榜单&#xff0c;该项目致力于发掘和表彰蓬勃成长、持续创新、积极承担社会责任的卓越企业。该榜单1995 年创立至今&#xff0c;被业界誉为“全球高成长企业的标杆”。Authing 凭借在 IDaaS&#xff08;身份云&#xff09; 领域突…...

单片机嵌入式操作系统内核

1、前后台系统&#xff0c;协作式内核系统&#xff0c;与占先式内核系统&#xff0c;有什么不同呢&#xff1f; 记得在 21IC 上看过这样的比喻, 你(小工)在用厕所&#xff0c;经理在外面排第一&#xff0c;老板在外面排第二。 如果是前后台&#xff0c;不管是谁&#xff0c;都…...

C语言——柔性数组

目录0. 前言1. 思维导图2. 柔性数组的特点3. 柔性数组的使用4. 柔性数组的优势5. 结语0. 前言 柔性数组是在C99标准时引入&#xff1a; 结构中的最后一个元素允许是未知大小的数组&#xff0c;这就叫柔性数组成员。 代码示例&#xff1a; typedef struct flexible_arr {int a…...

web人脸登录

1&#xff0c;需要腾讯人脸第三方 腾讯人脸第三方申请步骤 2&#xff0c;相关表结构设计 create database faceDB;use faceDB; -- 人脸表 create table face( fid int primary key auto_increment COMMENT 主键, face_base longtext COMMENT 图片数据 base_64编码, create_tim…...

C++数字

目录 一、什么是数字 二、定义数字 三、数学运算 四、随机数 一、什么是数字 通常&#xff0c;当我们需要用到数字时&#xff0c;我们会使用原始的数据类型&#xff0c;如 int、short、long、float 和 double 等等。这些用于数字的数据类型&#xff0c;其可能的值和数值范围…...

【python】用plotly绘制正二十面体

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

[Datawhale][CS224W]图机器学习(五)

这里写目录标题一、Deepwalk1.1 预备知识1.2 Deepwalk介绍1.3 Embedding1.4 word2Vec 词向量&#xff0c;词嵌入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命令启动 这种方式比较简单&#xff0c;但是窗口关闭后服务也就被杀死了&#xff0c;命令如下 java -jar xxx.jar2、bat脚…...

【图像分类】卷积神经网络之AlexNet网络模型结构详解

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 1. 前言 LeNet5网络模型提出之后,卷积神经网络在很长一段时间都没有长足的发展,主要有以下两个原因: 1.1 训…...

学习动漫插画的网络班排行榜

很多小伙伴不知道动漫插画培训机构哪个好&#xff0c;找不到靠谱的插画班&#xff0c;今天给大家整理了国内动漫插画培训机构排名&#xff01; 一&#xff1a;动漫插画培训机构排名 1、轻微课&#xff08;五颗星&#xff09; 主打课程有日系插画、游戏原画、古风插画、动漫漫画…...

SpringCloud第五讲 Nacos注册中心-服务注册到Nacos

1.引入依赖&#xff1a; 在父工程中添加spring-cloud-alibaba的管理依赖 <!-- Nacos的管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version…...

IP地理位置定位技术原理是什么

IP地理位置定位技术的原理是基于IP地址的网络通信原理和基础上的。它利用IP地址所包含的一些信息&#xff0c;如网络前缀和地址段&#xff0c;以及ISP的IP地址归属地数据库&#xff0c;来推测IP地址所对应的地理位置。具体来说&#xff0c;IP地址是由32位二进制数字组成的&…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

LLM基础1_语言模型如何处理文本

基于GitHub项目&#xff1a;https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken&#xff1a;OpenAI开发的专业"分词器" torch&#xff1a;Facebook开发的强力计算引擎&#xff0c;相当于超级计算器 理解词嵌入&#xff1a;给词语画"…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...