【线程】POSIX信号量---基于环形队列的生产消费者模型
信号量概念
这篇文章是以前写的,里面讲了 System V的信号量的概念,POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。
信号量的概念
POSIX信号量的接口
初始化信号量

参数:
pshared:0表示线程间共享,非0表示进程间共享
value:信号量初始值,资源的初始值
销毁信号量

等待信号量,P操作,表示要使用资源,将信号量值加1

发布信号量,V操作,表示资源使用完毕,可以归还资源了,将信号量值加1

基于环形队列的生产消费者模型
生产消费者模型
这篇文章里的生产者消费者模型,是基于一个queue展开了,也就是把queue当成一个整体来看,当成一个资源,我们对他进行加锁保护(锁就相当于二元信号量)。下面我们把这个生产者消费者模型改一下,是基于环形队列的,不把环形队列看成一个整体,把环形队列里的每个块看成很多个资源,这时候线程并发访问时会产生问题,就需要用信号量来解决
环形队列采用数组模拟,用模运算来模拟环状特性,生产者Prpducter向队列里生产任务,消费者Consumer向队列里拿数据
怎么判空和满?
当P,V指向同一个位置的时候,就是空或者满

怎么保证它们不访问同一个位置? 用信号量来管理
生产者关注的是空间资源,消费者关注的是数据资源,这两种资源可以分别用两种信号量来管理 ,假如开始的时候,空间资源是队列的大小,数据资源为0,此时生产者可以申请空间资源信号量成功,他就可以生产,但是消费者申请数据资源信号量时就失败等待,用两个信号量来管理者两个资源就可以很好的让生产者消费者同时访问同一个队列,但是不会访问到同一个位置,就可以很好的解决上面的问题
实现代码
大家可以把他们复制到VS Code下来看
main.cc
#include<iostream>
#include<ctime>
#include<unistd.h>
#include"RingQueue.hpp"
#include"task.hpp"using namespace std;
struct ThreadData
{RingQueue<Task>* rq;string threadname;
};void* Consumer(void* args)
{ThreadData* data=static_cast<ThreadData*>(args);RingQueue<Task>* rq=data->rq;string name=data->threadname;while(true){//消费任务Task t;rq->Pop(&t);//处理任务t.run();printf("消费者得到一个任务:%s,who:%s,结果:%s\n",t.GetTask().c_str(),name.c_str(),t.GetResult().c_str());//用printf输出比较好,不会错乱,cout打印有时会错乱// cout<<"消费者得到一个任务:"<<t.GetTask()<<",who: "<<name<<",结果为:"<<t.GetResult()<<endl;// sleep(1);}return nullptr;
}
void* Producter(void* args)
{ThreadData* data=static_cast<ThreadData*>(args);RingQueue<Task>* rq=data->rq;string name=data->threadname;while(true){//获取数据int data1=rand()%10+1;int data2=rand()%5;char op=opers[rand()%opers.size()];Task t(data1,data2,op);//生产任务rq->Push(t);printf("生产者生产一个任务:%s,who:%s\n",t.GetTask().c_str(),name.c_str());//用printf输出比较好,不会错乱,cout打印有时会错乱// cout<<"生产者生产一个任务:"<<t.GetTask()<<",who: "<<name<<endl;sleep(1);}return nullptr;
}int main()
{srand(time(nullptr));RingQueue<Task>* rq=new RingQueue<Task>(10);pthread_t c[5], p[3];for (int i = 0; i < 3; i++){ThreadData *td = new ThreadData();td->rq = rq;td->threadname = "Productor-" + std::to_string(i);pthread_create(p + i, nullptr, Producter, td);}for (int i = 0; i < 5; i++){ThreadData *td = new ThreadData();td->rq = rq;td->threadname = "Consumer-" + std::to_string(i);pthread_create(c + i, nullptr, Consumer, td);}for (int i = 0; i < 3; i++){pthread_join(p[i], nullptr);}for (int i = 0; i < 5; i++){pthread_join(c[i], nullptr);}return 0;
}
RingQueue.hpp
#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<pthread.h>
#include <semaphore.h>using namespace std;template<class T>
class RingQueue
{
public:void P(sem_t& sem){sem_wait(&sem);}void V(sem_t& sem){sem_post(&sem);}void Lock(pthread_mutex_t& mutex){pthread_mutex_lock(&mutex);}void Unlock(pthread_mutex_t& mutex){pthread_mutex_unlock(&mutex);}
public:RingQueue(int maxcap=5):maxcap_(maxcap),ringqueue_(maxcap),c_index_(0),p_index_(0){sem_init(&cdata_sem_,0,0);sem_init(&pspace_sem_,0,maxcap);pthread_mutex_init(&c_mutex_,nullptr);pthread_mutex_init(&p_mutex_,nullptr);}void Push(const T& in)//生产{P(pspace_sem_);//生产者关注空间资源,申请空间资源,空间资源--Lock(p_mutex_);//下标也是共享资源,需要加锁保护ringqueue_[p_index_]=in;p_index_++;p_index_%=maxcap_;//维持环形特性Unlock(p_mutex_);V(cdata_sem_);//数据资源增多了,数据资源++}void Pop(T* out)//消费{P(cdata_sem_);//消费者关注数据资源,申请数据资源,数据资源--Lock(c_mutex_);//下标也是共享资源,需要加锁保护*out=ringqueue_[c_index_];c_index_++;c_index_%=maxcap_;//维持环形特性Unlock(c_mutex_);V(pspace_sem_);//消费了数据,空间就增多了}~RingQueue(){sem_destroy(&cdata_sem_);sem_destroy(&pspace_sem_);pthread_mutex_destroy(&c_mutex_);pthread_mutex_destroy(&p_mutex_);}private:vector<T> ringqueue_;//用数组模拟环形队列int maxcap_;//环形队列的最大容量int c_index_;//消费者的下标int p_index_;//生产者的下标sem_t cdata_sem_;//消费者关注的数据资源sem_t pspace_sem_;//生产者关注的空间资源pthread_mutex_t c_mutex_;pthread_mutex_t p_mutex_;
};
Task.hpp
#pragma once
#include <iostream>
#include <string>using namespace std;
string opers="+-*/%";enum
{Divzero = 1,Modzero,Unknown
};class Task
{
public:Task(){}Task(int data1, int data2, char op) : _data1(data1), _data2(data2), _op(op), _result(0), _exitcode(0){}void run(){switch (_op){case '+':{_result = _data1+_data2;break;}case '-':{_result = _data1-_data2;break;}case '*':{_result = _data1*_data2;break;}case '/':{if (_data2 == 0) _exitcode = Divzero;else _result = _data1/_data2;break;}case '%':{if (_data2 == 0) _exitcode = Modzero;else _result = _data1%_data2;break;}default:{_exitcode=Unknown;break;}}}void operator()(){run();}string GetResult(){string r=to_string(_data1);r+=_op;r+=to_string(_data2);r+='=';r+=to_string(_result);r+='[';r+=to_string(_exitcode);r+=']';return r;}string GetTask(){string r=to_string(_data1);r+=_op;r+=to_string(_data2);r+="=?";return r;}private:int _data1;int _data2;char _op;int _result;int _exitcode;
};
相关文章:
【线程】POSIX信号量---基于环形队列的生产消费者模型
信号量概念 这篇文章是以前写的,里面讲了 System V的信号量的概念,POSIX信号量和SystemV信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的。 但POSIX可以用于线程间同步。 信号量的概念 POSIX信号量的接口 初始化…...
Excel 设置自动换行
背景 版本:office 专业版 11.0 表格内输入长信息,发现默认状态时未自动换行的,找了很久设置按钮,遂总结成经验帖。 操作 1)选中需设置的单元格/区域/行/列。 2)点击【开始】下【对齐方式】中的【自动换…...
UNI-SOP使用说明
UNI-SOP提供了两个集成客户端:SpringBoot2.x/JAVA1.8和SpringBoot3.x/JAVA17,满足不同项目的集成需求。 平台接入 使用UNI-SOP之前,业务平台需要进行接入,完成校验后才能正常使用,先引入客户端开发SKD包。 <depen…...
记录-java web 生成并下载zip文件
java生成zip文件,zip文件分两种:一种是包含文件夹、一种是不包含文件夹 生成zip文件的方式 ZipOutputStream zipOutputStream new ZipOutputStream(response.getOutputStream());// 文件夹名称String folder "download/";ZipEntry ze new Z…...
大数据集群部署文档
大数据集群部署文档 注意:需配合大数据集群启动&检查文档进行部署,以便可以检验每一个组件是否部署成功。 文章目录 大数据集群部署文档一、部署前准备1. 确保所有机器可以访问外网2. 配置root用户ssh连接3. 解决Vmware ESXi 6.5 Ubuntu虚拟机ssh连…...
HTML中的表单(超详细)
一、表单 1.语法 <!-- action:提交的地方 method:提交的方式(get会显示,post不会) --> <form action"#" method"get"><p>名字:<input name"name" ty…...
初识 C 语言(一)
目录 一、 第一个 C 程序1. printf() 函数和 stdio.h 头文件2. main() 函数和 return 语句 二、类型和变量1. C 语言中的基本类型2. 变量的创建和命名规则3. 类型和变量的大小 三、printf() 函数和 scanf() 函数1. printf() 函数的使用2. 各种类型的输出格式3. scanf() 函数的使…...
LiveNVR监控流媒体Onvif/RTSP功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大
LiveNVR监控流媒体Onvif/RTSP功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大 1、视频广场2、录像回看3、RTSP/HLS/FLV/RTMP拉流Onvif流媒体服务 1、视频广场 视频广场 -》播放 ,左键单击可以拉取矩形框,放大选中的范围ÿ…...
element ui中当el-dialog需要做全屏时,.fullscreen样式修改问题
element ui 饿了么UI中el-dialog样式修改问题 场景解决方法就是:去掉底部样式中的scoped,然后再进行页面级样式的更改即可。 场景 最近在使用element-ui时,使用到了弹窗组件: element-ui 官网链接地址: element-ui 官网链接地址…...
C++的明星之我是类001
文章目录 类类定义格式访问限定符类域 实例化实例化概念对象大小 this指针两道nt题目题目一题目二 C和C语言实现stack对比 类 类定义格式 新增一个关键字class,后加上类的名字,{}中为类的主体,类中的函数称为类的⽅法或者成员函数定义在类⾯…...
深度学习与应用:行人跟踪
**实验 深度学习与应用:行人跟踪 ** ------ **1、 实验目的** ------ - 了解行人跟踪模型基础处理流程 - 熟悉行人跟踪模型的基本原理 - 掌握 行人跟踪模型的参数微调训练以及推理的能力 - 掌握行人跟踪模型对实际问题的应用能力,了解如何在特定的场景和…...
MySQL | DATE_ADD()函数
题1: 现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率。请你取出相应数据。 示例:question_practice_detail iddevice_idquest_idresultdate12138111wrong2021-05-0323214112wrong2021-05-0933214113wrong2021-06-1546543111right2021…...
DVWA 靶场环境搭建
作者:程序那点事儿 日期:2024/09/15 09:30 什么是DVWA: 是OWSASP官方编写的PHP网站,包含了各种网站常见漏洞(漏洞靶场),可以学习攻击及修复方式。 PHP环境包含了,Windows/Apache/Mysql/Php g…...
Autosar学习----AUTOSAR_SWS_BSWGeneral(七)
💥💥🔍 🔍 欢迎来到本博客❤️❤️💥💥 🐡优势:❤️博客内容尽量做到通俗易懂,逻辑清晰。 ⛳️座右铭:恒心,耐心,静心。 ⛳️ 欢迎一起…...
自动化测试框架集成:将Selenium集成到pytest与unittest中
目录 引言 一、Selenium简介 二、Selenium与pytest的集成 1. 安装pytest和Selenium 2. 编写测试用例 3. 运行测试 三、Selenium与unittest的集成 1. 编写测试类 2. 运行测试 四、Selenium自动化测试的最佳实践 1. 使用Page Object模式 2. 合理利用等待机制 3. 跨浏…...
华为GaussDB数据库(单机版)在ARM环境下的安装指南
一、软件版本 机器配置:8核16G,CPU: Huawei Kunpeng 920 2.9GHz操作系统:EulerOS 2.8 64bit with ARM数据库版本:GaussDB Kernel 505.1.0 build 44f4fa53 二、部署流程 2.1 新建用户 ① 以omm用户为例,添加一个omm用…...
计算机网络笔记002
### 课堂讨论对话 **学生A**: 老师,计算机网络的组成是怎样的?🤔 **老师**: 非常好的问题!计算机网络主要由硬件、软件和通信协议三部分组成。我们先从硬件开始讨论吧。 **学生B**: 硬件包括哪些设备呢?ὠ…...
Unity 的Event的Use()方法
对于Event的Use方法,其在调用后将不会再判断同类型的事件 这种情况下,第二个MosueDown不会进入,因为已经Use 如果把Use注释掉 依旧能进入第二个MosueDown 也就是说当使用了Use方法,相同的事件类型不会进第二遍...
数据分析师之Excel数据清洗
前言 目前,掌握一定的Excel技能时,怎么通过自己的技能实现数据分析的操作,就需要进行具体项目的实战,本身数据分析这个行业是非常吃经验的,既然我们是小白入坑,就需要多做实战演练,才能够实际的…...
手机解压软件加密指南:让文件更安全
在数字化时代,文件加密对于保护个人隐私和敏感信息的重要性不言而喻。随着互联网的飞速发展,我们的生活和工作越来越依赖于数字设备和网络。 然而,这也带来了一系列的安全风险,如黑客攻击、数据泄露等。文件加密技术成为了保护我…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
加密通信 + 行为分析:运营商行业安全防御体系重构
在数字经济蓬勃发展的时代,运营商作为信息通信网络的核心枢纽,承载着海量用户数据与关键业务传输,其安全防御体系的可靠性直接关乎国家安全、社会稳定与企业发展。随着网络攻击手段的不断升级,传统安全防护体系逐渐暴露出局限性&a…...
拟合问题处理
在机器学习中,核心任务通常围绕模型训练和性能提升展开,但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正: 一、机器学习的核心任务框架 机…...
