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

13.POSIX信号量

一.System V信号量

可以看往期博客(了解即可,怎么使用的根据兴趣)

https://blog.csdn.net/weixin_60668256/article/details/154446673?fromshare=blogdetail&sharetype=blogdetail&sharerId=154446673&sharerefer=PC&sharesource=weixin_60668256&sharefrom=from_link

太麻烦了,我们直接使用POSIX信号量

二.POSIX信号量

1.信号量的讲解

我们在进行写抢票代码的时候,将我们对应的票,当作我们对应的整体使用

所以,互斥锁本身就是信号量的一种

2.POSIX信号量的接口

三.环形队列的生产消费模型

1.讲解环形队列

如果我们要设计一个环形队列的话,我们应该有两个信号量(一个data,一个space)

2.环形队列整体调用代码

#include "RingBuffer.hpp"
#include <pthread.h>
#include <unistd.h>
#include <ctime>using namespace RingBufferModule;void* Consumer(void* args)
{RingBUffer<int>* ring_buffer = static_cast<RingBUffer<int>*>(args);while(true){int data;ring_buffer->Pop(&data);}
}void* Productor(void* args)
{RingBUffer<int>* ring_buffer = static_cast<RingBUffer<int>*>(args);int data = 10;while(true){ring_buffer->Equeue(10);}
}int main()
{RingBUffer<int>* ring_buffer = new RingBUffer<int>();//共享资源 -> 临界资源//单生产,单消费pthread_t c1,p1;pthread_create(&c1,nullptr,Consumer,ring_buffer);pthread_create(&p1,nullptr,Productor,ring_buffer);pthread_join(c1,nullptr);pthread_join(p1,nullptr);delete ring_buffer;return 0;
}

3.环形队列框架设计

#pragma once#include <iostream>
#include <vector>
#include <semaphore.h>namespace RingBufferModule
{template<class T>class RingBUffer{public:RingBuffer(){}void Equeue(const T& in){//生产者}void Pop(T* out){//消费者}~RingBuffer(){}private:std::vector<T> _ring;    //环,临界资源int _cap;                //容量int _p_step;             //生产者位置int _c_step;             //消费者位置sem_t _datasem;          //数据信号量sem_t _spacesem;         //空间信号量};
}

4.Sem封装

#pragma once
#include <semaphore.h>namespace SemModule
{int defalutsemval = 1;class Sem{public:Sem(int value = defalutsemval) : _init_value(value){int n = ::sem_init(&_sem, 0, _init_value);(void)n;}void P(){int n = ::sem_wait(&_sem);//就是--(void)n;}void V(){int n = ::sem_post(&_sem);//就是++(void)n;}~Sem(){int n = ::sem_destroy(&_sem);(void)n;}private:sem_t _sem;int _init_value;};
} // namespace SemModule

5.RingBuffer构造函数

RingBuffer(int cap):_ring(cap),_cap(cap),_p_step(0),_c_step(0),_datasem(0),_spacesem(cap){}

6.Equeue函数

void Equeue(const T& in){//生产者_spacesem.P();_ring[_p_step] = in;_P_step++;_p_step %= _cap;_datasem.V();}

7.Pop函数

void Pop(T* out){//消费者_datasem.P();*out = _ring[_c_step];_c_step++;_c_step %= _cap;_spacesem.V();}

8.总代码

#pragma once#include <iostream>
#include <vector>
#include "Sem.hpp"namespace RingBufferModule
{using namespace SemModule;template<class T>class RingBuffer{public:RingBuffer(int cap):_ring(cap),_cap(cap),_p_step(0),_c_step(0),_datasem(0),_spacesem(cap){}void Equeue(const T& in){//生产者_spacesem.P();_ring[_p_step] = in;_P_step++;_p_step %= _cap;_datasem.V();}void Pop(T* out){//消费者_datasem.P();*out = _ring[_c_step];_c_step++;_c_step %= _cap;_spacesem.V();}~RingBuffer(){}private:std::vector<T> _ring;    //环,临界资源int _cap;                //容量int _p_step;             //生产者位置int _c_step;             //消费者位置Sem _datasem;          //数据信号量Sem _spacesem;         //空间信号量};
}

就相当于是,将我们对应得mutex和cond进行了封装

四.测试

1.单生产,单消费

#include "RingBuffer.hpp"
#include <pthread.h>
#include <unistd.h>
#include <ctime>using namespace RingBufferModule;void* Consumer(void* args)
{RingBuffer<int>* ring_buffer = static_cast<RingBuffer<int>*>(args);while(true){sleep(1);int data;ring_buffer->Pop(&data);std::cout << "消费了一个数据: " << data << std::endl;}
}void* Productor(void* args)
{RingBuffer<int>* ring_buffer = static_cast<RingBuffer<int>*>(args);int data = 0;while(true){ring_buffer->Equeue(data);std::cout << "生产了一个数据: " << data << std::endl;data++;}
}int main()
{RingBuffer<int>* ring_buffer = new RingBuffer<int>(5);//共享资源 -> 临界资源//单生产,单消费pthread_t c1,p1;pthread_create(&c1,nullptr,Consumer,ring_buffer);pthread_create(&p1,nullptr,Productor,ring_buffer);pthread_join(c1,nullptr);pthread_join(p1,nullptr);delete ring_buffer;return 0;
}

为啥我们在这个代码里面,没有进行判断呢?

他将资源是否可使用,转化成是否申请成功信号量(只要申请成功就一定有资源),要等待也是在信号量上面进行等待

生产者和消费者之间的关系,由我们对应的信号量来进行维护了

2.多生产,多消费

生产者之间要加锁,由一个生产者为代表,来进入我们对应的环形队列里面(消费者也是同理)

修改代码如下:

#pragma once#include <iostream>
#include <vector>
#include "Sem.hpp"namespace RingBufferModule
{using namespace SemModule;template<class T>class RingBuffer{public:RingBuffer(int cap):_ring(cap),_cap(cap),_p_step(0),_c_step(0),_datasem(0),_spacesem(cap){pthread_mutex_init(&_p_lock);pthread_mutex_init(&_c_lock);}void Equeue(const T& in){//生产者pthread_mutex_lock(&_p_lock);_spacesem.P();_ring[_p_step] = in;_P_step++;_p_step %= _cap;_datasem.V();pthread_mutex_unlock(&_p_lock);}void Pop(T* out){pthread_mutex_lock(&_c_lock);//消费者_datasem.P();*out = _ring[_c_step];_c_step++;_c_step %= _cap;_spacesem.V();pthread_mutex_unlock(&_c_lock);}~RingBuffer(){pthread_mutex_destroy(&_p_lock);pthread_mutex_destroy(&_c_lock);}private:std::vector<T> _ring;    //环,临界资源int _cap;                //容量int _p_step;             //生产者位置int _c_step;             //消费者位置Sem _datasem;            //数据信号量Sem _spacesem;           //空间信号量pthread_mutex_t _p_lock; //生产者之间的锁pthread_mutex_t _c_lock; //消费者之间的锁};
}

先申请信号量,再申请锁,还是先申请锁还是先信号量呢?

答案是先进行申请信号量,拿这信号量,再竞争锁资源(这样较快)

3.封装代码

#pragma once#include <iostream>
#include <vector>
#include "Sem.hpp"
#include "Mutex.hpp"namespace RingBufferModule
{using namespace SemModule;using namespace LockModule;template<class T>class RingBuffer{public:RingBuffer(int cap):_ring(cap),_cap(cap),_p_step(0),_c_step(0),_datasem(0),_spacesem(cap){}void Equeue(const T& in){//生产者_spacesem.P();{LockGuard lockguard(_p_lock);_ring[_p_step] = in;_P_step++;_p_step %= _cap;}_datasem.V();}void Pop(T* out){//消费者_datasem.P();{LockGuard lockguard(_c_lock);*out = _ring[_c_step];_c_step++;_c_step %= _cap;}_spacesem.V();}~RingBuffer(){}private:std::vector<T> _ring;    //环,临界资源int _cap;                //容量int _p_step;             //生产者位置int _c_step;             //消费者位置Sem _datasem;            //数据信号量Sem _spacesem;           //空间信号量Mutex _p_lock; //生产者之间的锁Mutex _c_lock; //消费者之间的锁};
}

http://www.dtcms.com/a/590083.html

相关文章:

  • 网站开发实习深圳外贸公司名单
  • Node.js后端框架Express.js
  • 网站建设不用备案的淘宝网网页版入口
  • 创意互动网站jsp做网站视频教程
  • 普中51单片机学习笔记-流水灯
  • 先备案先建网站运城市住房和城乡建设厅网站
  • 制作网站要什么软件app运营成本估算
  • MBSE与数字孪生:五大行业案例
  • 火狐安装uBlock广告拦截工具
  • AActor前面为什么要加A? UObject前面为什么要加U?
  • C++ 变量作用域 存储期 链接性:const / static / extern 全面解析
  • 五星酒店网站建设方案公司换网站换域名 备案
  • 阿里云虚拟主机装WordPress网站优化三要素
  • 用网站做淘客怎么赚钱奉化区建设局网站
  • 网站建设做什么抖音广告投放平台官网
  • 前端展示印度市场的核心股票
  • 宁波seo网站排名怎样在网站做友情链接
  • 国外网站大全帝国cms模板wordpress批量注册用户
  • Zabbix6聚合算法
  • 城阳做网站的公司在山东省建设监理协会网站
  • 瑞数——网上房地产补环境cookie及后缀XJlCTRRM获取
  • 韩国网站设计风格送菜上门网站app如何做
  • 在 Linux 中管理与安装字体(详细教程)
  • 中山哪里网站建设网站建设 壹起航
  • Python全栈项目:结合Puppeteer和AI模型操作浏览器
  • 中国建设银行 网站登录企业邮箱注册申请免费注册入口
  • 多输出电压条件下同步整流效率测试与优化
  • 六安市裕安区建设局网站wordpress导航栏颜色
  • 梨树县住房和城乡建设局网站在线短网址生成工具
  • 【stm32】【DFU】