LINUX系统编程:基于环形队列和信号量的生产者消费者模型

目录

1.环形队列

2.加上信号量的理解

3.代码


1.环形队列

环形队列使用vector封装出来的。

环形队列可以实现并发生产和消费,就是在消费的同时也可以生产。

这个是建立在生产者消费者位置不重合的情况下。

因为位置重合之后,环形队列为空或者满,

为空的时,只能让生产者先生产,消费者后消费,

为满时,消费者先消费,生产者后生产。

如何实现环形的效果

当下标遍历到vector末尾的时候, 下标 %=判断环形队列为空还是为满 vector容量,下标就回到数组的开始。

当生产者消费者重合时

1.队列为空(访问环形队列,让生产者先生产)

2.队列为满(访问环形队列,让消费者先消费)

当生产者与消费者不重合时

队列一定不为空&&不为满,这个时候生产者可以生产,消费者可以消费。

2.加上信号量的理解

生产者只关心环形队列有没有空间让他生产

消费者只关心环形队列有没有数据让他消费

信号量是一种资源预定机制,预定成功之后肯定会有空间和数据,给消费者和生产者

所以生产者在生产之前要对空间的信号量进行p操作,生产完成之后要对数据的信号量进行v操作

所以消费者在生产之前要对数据的信号量进行p操作,消费完成之后要对空间的信号量进行v操作

3.代码

ringqueue.hpp

#ifndef __RINGQUEUEHPP__
#define __RINGQUEUEHPP__
#include<pthread.h>
#include<thread>
#include<vector>
#include<semaphore.h>
#include"Task.hpp"
#include <iostream>
#include <string.h>
template<class T>
class ringqueue
{
private:void p(sem_t &sem){int ret = sem_wait(&sem);if(ret == -1){std::cout<< strerror(errno) <<std::endl;}}void v(sem_t &sem){int ret = sem_post(&sem);if(ret == -1){std::cout<< strerror(errno) <<std::endl;}}public:ringqueue(int cap = 8):_ringqueue(cap),_cap(cap),p_step(0),c_step(0){sem_init(&_room,0,cap);sem_init(&_data,0,0);pthread_mutex_init(&c_mutex,nullptr);pthread_mutex_init(&p_mutex,nullptr);}//生产者向队列里生产void enqueue(T in){   p(_room); // 申请空间pthread_mutex_lock(&p_mutex);_ringqueue[p_step++] = in;p_step %= _cap;pthread_mutex_unlock(&p_mutex);v(_data); // 生产之后资源++}   void pop(T &out){//int roomnum = 0;//int datanum = 0;//sem_getvalue(&_room,&roomnum);//sem_getvalue(&_data,&datanum);//std::cout<< roomnum <<" " <<datanum <<std::endl;p(_data); //申请资源pthread_mutex_lock(&c_mutex);out = _ringqueue[c_step++];c_step %= _cap;pthread_mutex_unlock(&c_mutex);v(_room);}~ringqueue(){sem_destroy(&_room);sem_destroy(&_data);pthread_mutex_destroy(&p_mutex);pthread_mutex_destroy(&c_mutex);}private:std::vector<T> _ringqueue;int _cap;//容量int p_step ;//生产者下次生产的位置int c_step ;//消费者下次消费的位置sem_t _room; //空间sem_t _data; //资源pthread_mutex_t p_mutex; //为了多生产之间的互斥关系pthread_mutex_t c_mutex; //为了多消费之间的互斥关系
};#endif

Task.hpp

#ifndef __TASKHPP__
#define __TASKHPP__#include<string>
#include<iostream>
class Task
{
public:Task():taskname("未知任务"){}Task(std::string name):taskname(name){}void excute(){std::cout<<"Excute " << taskname <<std::endl;}std::string & name(){return taskname;}
private:std::string taskname;
};#endif

Main.cc

#include "Task.hpp"
#include "ringqueue.hpp"
#include <iostream>
#include <thread>
#include <string>
#include <vector>
#include <time.h>
#include <unistd.h>
std::vector<std::string> Taskarr{"Download", "UPLoad", "cacluate"};void product(void* args)
{ringqueue<Task>* rq = (ringqueue<Task>*)args;srand(time(nullptr));while (true){sleep(1);Task task(Taskarr[rand() % 3]);rq->enqueue(task);std::cout << "product task "<< task.name() << std::endl;}
}//void consum(ringqueue<Task> &rq)
//用指針的方式传递参数,把ringqueue的指针传过来,
void consum(void* args)
{ringqueue<Task>* rq = (ringqueue<Task>*)args;sleep(6);while (true){sleep(1);Task task;rq->pop(task);task.excute(); }
}
//是不是这里的问题 这里传过去的时候发生了拷贝
//是的
void product_start(std::vector<std::thread> &threadss, ringqueue<Task> &rq, int num)
{for (int i = 0; i < num; i++){threadss.emplace_back(product, (void*)&rq);}
}void consumer_start(std::vector<std::thread> &threadss, ringqueue<Task> &rq, int num)
{for (int i = 0; i < num; i++){threadss.emplace_back(consum, (void*)&rq);}
}void Waitall(std::vector<std::thread> &threadss)
{for (auto &thread : threadss){thread.join();}
}int main()
{std::vector<std::thread> threadss;ringqueue<Task> rq(5);product_start(threadss, rq,3);consumer_start(threadss, rq, 5);Waitall(threadss);return 0;
}

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

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

相关文章

Linux DRM 那些事 - HDMI 接口 DTS 配置

本文基于RockPI 4A单板Debian系统 Linux 4.4 内核介绍DRM框架HDMI接口DTS配置。 在DTS中主要实现&#xff1a;HDMI的使能、VOP绑定、IOMUX引脚配置和HDMI控制器配置。 一、HDMI 配置 文件&#xff1a;arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dtsi #include "rk3…

C++ 宏

C中的宏是一种预处理指令&#xff0c;用于在编译时将代码中的标识符替换为指定的文本。 #define 指令 1.无参宏定义 无参宏的宏名后不带参数。 其定义的一般形式为&#xff1a; #define 标识符 字符串 其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命…

LLM 合成数据生成完整指南

大型语言模型是强大的工具&#xff0c;不仅可以生成类似人类的文本&#xff0c;还可以创建高质量的合成数据。这种能力正在改变我们进行 AI 开发的方式&#xff0c;特别是在现实世界数据稀缺、昂贵或隐私敏感的情况下。在本综合指南中&#xff0c;我们将探索 LLM 驱动的合成数据…

C语言——流程控制:if...else、switch...case

控制类语句&#xff1a; 逻辑运算符&#xff1a; 选择语句&#xff1a; if...else&#xff1a; if&#xff08;&#xff09;括号内的内容终究会被转换成0,1&#xff0c;满足的话即为1&#xff0c;不满足的话为0。因此要注意&#xff0c;&#xff08;&#xff09;括号内因为条件…

简单实现一个本地ChatGPT web服务(langchain框架)

简单实现一个本地ChatGPT 服务&#xff0c;用到langchain框架&#xff0c;fastapi,并且本地安装了ollama。 依赖安装&#xff1a; pip install langchain pip install langchain_community pip install langchain-cli # langchain v0.2 2024年5月最新版本 pip install bs4 pi…

ChatGPT摆脱“AI味”:全面提升写作质感

ChatGPT在各种写作、创作场景都发挥了很大的价值&#xff0c;即使中文语料库占比不到5%&#xff0c;也能生成流畅的中文文本。但随着使用的深入&#xff0c;大家也逐渐发现了机器生成的内容&#xff0c;往往带有一种僵硬、刻板的“AI味”&#xff0c;尤其在论文、自媒体写作中&…

算法力扣刷题记录 四十三【最大、最小深度问题】

前言 本文学习树的深度问题&#xff1a;二叉树&#xff08;N叉树&#xff09;最大深度、最小深度&#xff1b; 记录 三十九【层序遍历模版应用二】中解决过二叉树的最大深度和最小深度题目。思路是按层遍历&#xff1a; 最大深度&#xff0c;相当于层序遍历结束&#xff1b;…

ZBLOG程序怎么天收录?本人亲自试过请看以下教程(zblog怎么样)

您为管理员组&#xff0c;请查看下方隐藏内容&#xff01; 先去ZBLOG官网下载ZBLOG程序 直达地址https://www.zblogcn.com/ 安装到宝塔里 安装好了之后打开zblog的后台 点开应用中心搜索CMS自适应资讯主题免费 安装即可 安装了之后配置主题内容 有经验者可以去吧动态改成…

pnpm9.5.0(catalog协议)

catalog(目录协议) 目录是工作区功能&#xff0c;用于将依赖版本范围定义为可重用常量&#xff0c;目录中定义的常量可以在package.json中使用&#xff0c; 结合 pnpm-workspace.yaml使用 定义pnpm-workspace.yaml packages&#xff1a;定义多仓库 packages:- packages/*cata…

Flink异常:org/apache/hadoop/hive/ql/parse/SemanticException

在flink项目中跑 上面这段代码出现如下这个异常&#xff0c; java.lang.NoClassDefFoundError: org/apache/thrift/TException 加上下面这个依赖后不报错 <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId…

【逆向基础】十、工具分享之DIE(Detect It Easy)

一、简介 DIE&#xff08;Detect It Easy&#xff09;是一款可以轻松检测PE文件的程序&#xff1b;其主要作用是查壳&#xff0c;并将pe文件的内容解析出来&#xff0c;包括PE文件中包含的导入函数、导出函数的名称及地址&#xff0c;入口函数地址等&#xff0c;是技术人员分析…

lua 脚本语言 : 基础到高级语法

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

JupyterNotebook中导出当前环境,并存储为requirements.txt

​使用Anaconda管理Python环境时&#xff0c;可以轻松地导出环境配置&#xff0c;以便在其他机器或环境中重新创建相同的环境。可以通过生成一个environment.yml文件实现的&#xff0c;该文件包含了环境中安装的所有包及其版本。但是&#xff0c;常常在一些课程中JupyterNotebo…

微信小程序毕业设计-学习资料库系统项目开发实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计…

ProbTS:时间序列预测的统一评测框架

编者按&#xff1a;如今&#xff0c;时间序列预测在健康、能源、商业、气候等多个行业发挥着至关重要的作用。它不仅影响着相关资源的分配和调度&#xff0c;还影响着行业的管理和运营决策。但是现有的时间序列预测方法通常缺乏对基础预测需求的全面考虑&#xff0c;无论是经典…

JavaScript青少年简明教程:开发工具与运行环境

JavaScript青少年简明教程&#xff1a;开发工具与运行环境 JavaScript是一种基于对象和事件驱动且具有安全性能的脚本语言。使用它和HTML结合可以开发出交互式的Web页面。 脚本语言是为了缩短传统的编写-编译-链接-运行过程而创建的计算机编程语言。脚本通常是解释执行而非编…

阿里巴巴矢量图标库使用

阿里巴巴矢量图标库官网 添加图标到购物车 悬浮到图标上面会有个购物车icon,点击一下就可以添加购物车了 添加图标到项目 添加完购物车后,右上角会有当前在购物车的数量,点击右上角购物车icon,在新弹窗内点击添加至项目,选择添加到哪个项目(没有项目就创建一个),点击完成,…

Milvus 核心设计(1) ---- 数据一致性的等级及使用场景

目录 背景 Milvus的数据一致性 设置数据一致性等级 等级类型 PACELC定理 level 详细解释 Strong Bounded staleness Session Eventually 总结 背景 分布式上的可扩展性是个比较重要的concept。Chroma 核心之前写过了,他的最大优势在于轻量级且好用。Milvus相对Ch…

初识Spring Web MVC

1. 什么是 Spring Web MVC&#xff1f; Spring Web MVC 是基于 Servlet API 构建的原始 Web 框架&#xff0c;从⼀开始就包含在 Spring 框架中。它的正式名称“Spring Web MVC”来⾃其源模块的名称(Spring-webmvc)&#xff0c;但它通常被称为"SpringMVC".Servlet&am…

省市县下拉框的逻辑以及多表联查的实例

2024.7.12 一. 省市县的逻辑开发。1、准备&#xff1a;1.1. 要求&#xff1a;1.2 数据库表&#xff1a; 2. 逻辑&#xff1a;3. 方法3.1 创建实体类3.2 数据访问层3.3 实现递归方法3.4 控制器实现3.5 前端处理 二、多表联查&#xff08;给我干红温了&#xff09;1. 出现了问题2…