生产者消费者模式(c++实现)

news2024/10/6 20:22:51

生产者消费者模式思路就是:一批专门生产资源的线程 和一批专门处理资源的线程以及一个线程安全的任务队列组成的 。并且当任务队列满的时候阻塞生产线程,任务队列为空的时候阻塞消费线程。

要实现一个生产者消费者队列
1。需要实现线程同步,访问任务队列互斥
所以需要用到
条件变量 ,互斥锁
条件变量
wait 阻塞 当前线程 当满足条件的时候 调用 notify_one或notify_all 唤醒阻塞线程

当收到notify_one 唤醒一个线程
当收到notify_all唤醒所有线程

2.创建多个线程
thread t1(“func”);
“func” 为线程调用的处理函数
3.任务队列
可以使用queue实现

简单的生产者消费者模式实现需要有 以下几个方法
1.push 方法 用来给任务队列中添加任务,生产者任务调用
思路:
先加锁 判断当前队列size是否等于max_task_count(提前设置的最大任务数)
如果相等表示任务队列满了,则调用消息变量的wait()来阻塞生产者线程
如果任务队列没满则添加任务到消息队列中 并且唤醒消费者线程。(因为生产者如果成功生产了资源,消费者就可以在任务队列中拿到资源了)
在这里插入图片描述

2.pop 方法 用来从任务队列中取出任务,消费者任务调用
先加锁
判断队列是否为null
如果为空阻塞消费者线程
如果不为空 则获取一个任务,然后将这个任务在队列中删除
唤醒生产者线程;
在这里插入图片描述

3.pro_task方法 生产者任务方法(生产线程调用),调用push方法,向任务队列中添加任务
producer_count表示生产者生产了多少个任务
pro_count表示一共有多少个任务
while(1){
加锁
调用push方法添加一个任务
生成一个任务 使用了 function<void()> task 和bind(func,parm);
解锁
}
在这里插入图片描述

4.con_task方法 消费者任务方法(消费线程调用),调用pop方法,从任务队列中取出任务,执行任务。

while(1){
加锁
调用pop方法获取一个任务。
执行任务;
解锁
}
在这里插入图片描述

#include<mutex>
#include<thread>
#include<condition_variable>
#include<queue>
#include<iostream>
#include<functional>
#include<Windows.h>
using namespace std;

typedef function<void()> Task;
int max_task_count;//队列最大容量
int pro_count;//需要生产的资源数
int producer_count;//生产者已经生产数量
int consumer_count;//消费者消费数量
queue<Task> resouce;//任务队列
mutex m_mtx;//用来保护任务队列
mutex m_pro_mtx;//保护生产线程任务
mutex m_con_mtx;//保护消费线程任务
condition_variable pro_con;//实现生产线程同步
condition_variable con_con;//实现消费线程同步



void init(int max_task_num, int pro_num) {
	max_task_count = max_task_num;
	pro_count = pro_num;
	producer_count = 0;
	consumer_count = 0;
}

void func(int i) {
	cout << "task finish" << "-----" << i << endl;
}
//添加任务
void push(Task& task)
{
	//生产者给队列中添加任务
	unique_lock<mutex> lck(m_mtx);

	while (resouce.size() == max_task_count)
	{
		cout << "队列已经满了,生产者等待" << endl;
		pro_con.wait(lck);
	}
	resouce.push(task);
	//唤醒消费者线程
	con_con.notify_all();
}
//删除任务
Task pop()
{
	//消费者从队列中取出任务
	unique_lock<mutex>lck(m_mtx);
	while (resouce.size() == 0)
	{
		cout << "队列为空,消费者等待" << endl;
		con_con.wait(lck);
	}
	Task task = resouce.front();
	resouce.pop();
	//唤醒生产者线程
	pro_con.notify_all();
	return task;
}
//生产者
void proTask()
{
	while (1) {
		unique_lock<mutex> lck(m_pro_mtx);
		if (producer_count < pro_count) {
			producer_count++;
			Task task = bind(func, producer_count);
			push(task);
			cout << "生产者生成任务" << endl;

		}
		lck.unlock();
	}
}
//消费者
void conTask()
{
	while (1) {
		unique_lock<mutex> lck(m_con_mtx);
		if (consumer_count < pro_count) {
			consumer_count++;
			Task task = pop();
			cout << "消费者消费执行任务" << endl;
			task();
		}
		lck.unlock();
	}
}


int main()
{
	init(10, 20);

	thread pro1(proTask);
	thread pro2(proTask);
	thread pro3(proTask);

	thread con1(conTask);
	thread con2(conTask);
	thread con3(conTask);

	pro1.join();
	pro2.join();
	pro3.join();

	con1.join();
	con2.join();
	con3.join();


	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1121550.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

react的setState做了什么

1、为什么需要setState setState的作用是帮助我们更改数据的同时并且通知视图进行渲染。因为React并不会绑定视图和state&#xff0c;需要我们手动去更新视图。 2、setState什么时候是同步的&#xff0c;什么时候是异步的 setState这个方法在调用的时候是同步的&#xff0c;…

如果面试问到你redis的常用数据类型,你怎么和面试官聊上十分钟?

最近组长把一些简历推到我这边让我帮他面试几份&#xff0c;问到这种基础题目时收到的回答总是不太理想 1、最简单的回答&#xff1a; Redis存储的是key-value结构的数据&#xff0c;其中key是字符串类型&#xff0c;value有5种常用的数据类型&#xff1a; 字符串 string哈希 …

为什么spring默认采用单例bean

概 述 熟悉 Spring开发的朋友都知道 Spring 提供了 5种 scope&#xff0c;分别是&#xff1a; singleton: 单例模式&#xff0c;当spring创建applicationContext容器的时候&#xff0c;spring会欲初始化所有的该作用域实例&#xff0c;加上lazy-init就可以避免预处理&#xf…

磁盘分区如何分? 电脑磁盘分区免费软件指南!

列出并比较顶级免费磁盘分区管理器软件&#xff0c;以选择适用于 Windows 的最佳分区软件&#xff1a; 系统分区在现代计算机设备中起着非常重要的作用。它们可以存储数据&#xff0c;使系统文件远离用户数据&#xff0c;并在同一台设备上安装多个操作系统。但是&#xff0c;这…

MyBatis-Plus 实战教程一

这里写目录标题 简介快速上手数据库建立创建实体类修改参数引入依赖测试常见注解介绍TableNameTableIdTableField 常见配置仓库地址 简介 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;…

qt-C++笔记之信号与槽

qt-C笔记之信号与槽 code review! 本文抄自公众号&#xff1a;嵌入式小生 文章目录 qt-C笔记之信号与槽一.信号2.1.信号的发出2.2.信号的处理 二.槽函数2.1.带有默认参数的信号和槽函数2.2.使用QObject::connect()将信号连接到槽函数的三种方法2.2.1.第一种方法&#xff1a;使…

整理MongoDB文档:身份验证

整理MongoDB文档:身份验证 个人博客&#xff0c;求关注。 文章概叙 本文主要讲MongoDB在单机状态下的账户配置。理解了MongoDB的语法&#xff0c;对于如何配置用户权限会知道怎么配置&#xff0c;但是请注意给谁配置什么权限才是最重要的。 最小权限原则 系统的每个程序或者…

【C++编程语言】STL常用算法 算术生成和集合算法

1.算术生成算法概念 算法简介&#xff1a; accumlate 计算容器元素累计总和fill 向容器中添加元素 注意&#xff1a;算术生成算法属于小型算法 使用时包含头文件为#include<numeric> 2.accumulate /*函数原型&#xff1a;int accumulate(iterator beg ,iterator end…

热点不热!如何修复笔记本电脑未连接到移动热点的问题

当你远离常规Wi-Fi时,移动热点是让你的笔记本电脑上网的关键,但当它没有按计划运行时,你会怎么办?以下是Windows笔记本电脑无法连接到移动热点时的几种修复方法。 为什么我的笔记本电脑没有连接到我的热点 由于你的笔记本电脑正试图连接到另一个有限制和可能存在问题的设…

前端学成在线项目详细解析二

12-banner区域-课程表布局 HTML布局 <div class"right"><h3>我的课程表</h3><div class"content">1</div> </div> CSS样式 /* 课程表 */ .banner .right {margin-top: 60px;width: 218px;height: 305px;background-…

STM32F4_照相机

目录 前言 1. BMP编码 2. JPEG编码 前言 我们所要实现的照相机&#xff0c;支持BMP图片格式的照片和JPEG图片格式的照片。 1. BMP编码 BMP文件是由文件头、位图信息头、颜色信息和图形数据四部分构成。 1. BMP文件头&#xff08;14个字节&#xff09;&#xff1a;BMP文件…

在ESP32-Arduino开发中添加其它Arduino库

目录 前言 原理说明 操作步骤 下载Bounce 安装Bounce 将下载的文件夹(压缩包需要解压)移动到components/arduino/libraries路径下&#xff0c;并重命名为Bounce2 查看添加库里所有的源文件位置 在arduino的CMakeList.txt里添加库源文件 使用Bounce 前言 乐鑫官方的es…

HTTP介绍 原理 消息结构 客户端请求 服务器响应 HTTP状态码

一、HTTP介绍二、HTTP工作原理HTTP三点注意事项 三、HTTP消息结构四、客户端请求消息五、服务器响应消息HTTP请求方法 七、HTTP响应头信息八、HTTP状态码&#xff08;HTTP Status Code&#xff09;下面是常见的HTTP状态码&#xff1a;HTTP状态码分类HTTP状态码列表 一、HTTP介绍…

旁注、目录越权、跨库查询、cdn绕过

原理&#xff1a; 搭建网站多IP多端口&#xff0c;更多一个域名多网站&#xff0c;IIS的在属性-高级里面设置主机头设置域名&#xff0c;域名是收费的需要自己买一个 旁注&#xff1a;在同一服务器上有多个站点&#xff0c;要攻击的这个站点假设没有漏洞&#xff0c;可以攻击…

Spark大数据分析与实战笔记(第一章 Scala语言基础-5)

文章目录 每日一句正能量章节概要1.5 Scala的模式匹配与样例类1.5.1 模式匹配字符匹配匹配字符串守卫匹配类型匹配数组、元组、集合 1.5.2 样例类 课外补充偏函数 每日一句正能量 “成功的秘诀&#xff0c;在于对目标的执着追求。”——爱迪生 无论是在工作、学习、还是生活中&…

控制台的设置

目录 win32 API &#xff1a; 什么是API &#xff1a; 控制台&#xff1a; 控制台与VS&#xff1a; 控制台的控制&#xff1a; 控制台窗口设置&#xff1a; 1、mode函数&#xff1a; 2、title 函数&#xff1a; 在C语言中的实现&#xff1a; 控制台的坐标设置&#…

python 之numpy 之随机生成数

文章目录 1. **生成均匀分布的随机浮点数**&#xff1a;2. **生成随机整数**&#xff1a;3. **生成标准正态分布随机数**&#xff1a;4. **生成正态分布随机数**&#xff1a;5. **生成均匀分布的随机浮点数**&#xff1a;6. **生成随机抽样**&#xff1a;7. **设置随机数种子**…

Linux下Samba服务安装及启用全攻略

Linux下Samba服务安装及启用全攻略 前言一、安装SSH Server二、安装Samba Server1.安装net-tool2.建立账号的samba3.windows通过Samba与linux共享文件4.使用远程工具登录Linux 总结 前言 提示&#xff1a;本文详解了在Linux系统下如何安装和启用Samba服务&#xff0c;涵盖了从…

商家收款码手续费太高了

在竞争激烈、各行各业都如此内卷的当下&#xff0c;商家需要不断寻求提高利润的方法。所谓开源节流&#xff0c;既要学会提高利润率&#xff0c;也要学会节省成本&#xff0c;毕竟钱是挣出来的&#xff0c;同时也是省出来的。作为一个经常使用收款工具的商家&#xff0c;很多人…

Ubuntu源码编译samba

概述 本人最近研究samba的源码&#xff0c;但是在源码编译的时候&#xff0c;本以为直接config,make,make install。没想到编译过程中碰到很多麻烦&#xff0c;主要是各种依赖问题。 基于此&#xff0c;本文把samba编译的详细过程记录下来&#xff0c;以供再次研究借鉴。 软件…