Linux之信号量

目录

信号量

信号量相关接口

创建信号量

初始化信号量 

等待信号量,P操作

发布信号量,V操作 

销毁信号量

基于信号量的环形队列下的生产者和消费者模型 

环形队列

代码实现


上期我们学习了线程同步的概念,掌握了基于阻塞队列的生产者和消费者模型。基于阻塞队列的生产者和消费者模型,三种关系,两个角色,一个场所,现在我们要关注的就是这一个场所,在此模型中,我们把阻塞队列称为临界资源,但是基于此模型,有且仅有这一个临界资源,也就是说临界资源的数目只有这一个。但是很多场景下临界资源的数目并不只有一个,本期我们主要研究的就是临界资源不只有一个的场景下的生产者和消费者模型。

信号量

我们之前学习了临界资源的概念,临界资源其实就是可以被多个执行流访问的资源。上节课的生产者和消费者模型,只有超市这一个临界资源。还有一个场景,就是电影院这个场景,在电影中,电影院的座位可以被多个顾客使用,所以电影院的座位就是临界资源,且电影院的座位不单单只有一个,所以临界资源是有多个的。那么信号量是什么呢?

信号量用于描述临界资源的数目的大小,比如在电影院的模型下,信号量就可以表示座位的多少。 任何线程要访问临界资源,必须先申请信号量,访问完临界资源,必须释放信号量。申请信号量我们称为P操作,释放信号量我们称为V操作。

通过伪代码为大家讲述p操作和v操作。 

当然并不是所有临界资源都可以用信号量来表示其数目的多少。当一个临界资源可以被细分时,我们才可以用临界资源来表示临界资源的数目的多少,当一个临界资源被分成了多个小的临界资源时,此时就可以实现多个执行流共同访问临界资源,从而实现,多个执行流的并发,从而提高代码的执行效率。

信号量相关接口

信号量的接口与互斥锁接口和条件变量接口类似。

创建信号量

sem_t  sem;       //创建信号量 

初始化信号量 

int sem_init(sem_t *sem, int pshared, unsigned int value);          //初始化信号量

sem为创建的信号量的地址;pshared,0表示线程间共享,非0表示进程间共享;value表示信号量的初始值。

等待信号量,P操作

int sem_wait(sem_t *sem);           //P()

等待信号量,表示申请信号量,要使用资源。将信号量减1。

发布信号量,V操作 

sem_post(sem_t *sem);          //V()

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

销毁信号量

int sem_destroy(sem_t *sem);           //销毁信号量  

基于信号量的环形队列下的生产者和消费者模型 

环形队列

上图为一个环形队列,有生产者和消费者两个角色,环形队列为一个大的临界资源,这个大的临界资源有被分成了多个小部分,为多份小的临界资源。 

代码实现

生产者往环形队列中生产数据,消费者从环形队列中消费数据。生产者每生产一个数据前进一格,当生产者和消费者相遇时,要么是环形队列为空,要么是环形队列中的数据已满。基于此,我们对基于环形队列的生产者和消费者模型设立两个规则。

规则一:生产者不能把消费者逃一圈,因为一旦套了一圈,势必会造成相遇时,生产者和消费者所处的环形队列的那一块空间中数据的覆盖,造成数据丢失。

规则二:因为刚开始环形队列是为空的,所以刚开始一定是生产者先生产,然后再是消费者再进行消费,正是基于此,往后消费者的位置一定是不能超过生产者的。

生产者看重的是环形队列中的空白位置的数目,而消费者看重的是环形队列中数据的数目。所以创建两个信号量,一个信号量描述环形队列中空位置的数目,一个信号量描述环形队列中数据的数目。

代码实现如下。

 RingQueue.hpp

#include <iostream>
#include <vector>
#include <semaphore.h>namespace yjd
{const int DefaultCapacity = 10;template <class T>class RingQueue{public:RingQueue(const int &capacity = DefaultCapacity): _v(capacity){_capacity = capacity;sem_init(&_blank_sem, 0, 10);sem_init(&_data_sem, 0, 0);_c_step = _p_step = 0;}~RingQueue(){sem_destroy(&_blank_sem);sem_destroy(&_data_sem);}void push(T &data){sem_wait(&_blank_sem);_v[_p_step] = data;sem_post(&_data_sem);_p_step++;_p_step % _capacity;}void pop(T *data){sem_wait(&_data_sem);*data = _v[_c_step];sem_post(&_blank_sem);_c_step++;_c_step%_capacity;}private:std::vector<T> _v;int _capacity;// 描述空位置的数目sem_t _blank_sem;// 描述数据的数目sem_t _data_sem;int _p_step;int _c_step;};
}

整个代码的逻辑为,生产者先生产数据,然后消费者消费数据。生产者要生产数据,先申请一个空位置信号量,空位置信号量减1,然后生产数据,生产完数据之后,数据信号量加1;消费者消费数据时,先申请数据信号量,数据信号量减1,消费完数据之后,多了一个空位置,空位置信号量加1。

 RingCP.cc

#include "RingQueue.hpp"
#include <pthread.h>
#include <unistd.h>
#include <time.h>using namespace yjd;void *producter(void *args)
{RingQueue<int> *rq = (RingQueue<int> *)args;while (true){int data = rand() % 20 + 1;rq->push(data);std::cout << "生产者生产数据 " << data << std::endl;}
}void *consumer(void *args)
{RingQueue<int> *rq = (RingQueue<int> *)args;while (true){int data = 0;rq->pop(&data);std::cout << "消费者消费数据 " << data << std::endl;sleep(1);}
}int main()
{pthread_t c;pthread_t p;RingQueue<int> *rq = new RingQueue<int>();srand((long long)time(nullptr));pthread_create(&c, nullptr, consumer, (void *)rq);pthread_create(&p, nullptr, producter, (void *)rq);pthread_join(c, nullptr);pthread_join(p, nullptr);return 0;
}

运行结果如下。

通过运行结果可知,我们通过使用信号量和唤醒队列,实现了生产和消费者的同步。  

以上便是本期信号量的相关知识点。

本期内容到此结束 ^_^

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

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

相关文章

Redis--高可用(主从复制、哨兵模式、分片集群)

高可用&#xff08;主从复制、哨兵模式、分片集群&#xff09; 高可用性Redis如何实现高可用架构&#xff1f;主从复制原理1. 全量同步2. 命令传播3. 增量同步 Redis Sentinel&#xff08;哨兵模式&#xff09;为什么要有哨兵模式&#xff1f;哨兵机制是如何工作的&#xff1f;…

常用的数据结构API概览

List ArrayList 1、在初始化一个ArrayList的时候&#xff0c;如果我想同时set一些值 比如存放int[ ] List<int[]> list new ArrayList(Arrays.asList(new int[]{intervals[0][0],intervals[0][1]}));//或者int[] temp new int[]{intervals[0][0],intervals[0][1]}…

wordpress右侧浮动咨询台插件

简洁实用&#xff0c;操作方便&#xff0c;没有复杂的设置。 下载、安装、启用&#xff0c;即可使用。 wordpress在线客服插件-CS4&#xff0c;该插件适用于简站主题与精智主题。 下载 https://www.jianzhanpress.com/?p4622

Spring MVC实战指南:构建高效Web应用的架构与技巧(三)

响应数据和结果视图(7种) 返回值分类 创建web.xml&#xff08;spring、过滤器解决乱码、配置控制器dispatcherServlet、加载springmvc.xml文件、配置启动加载&#xff09;创建springmvc.xml文件 <!--配置了内容&#xff0c;启动Tomcat服务器的时候&#xff0c;就会被加载--…

使用LINUX的dd命令制作自己的img镜像

为了避免重复安装同一镜像&#xff0c;配置环境&#xff0c;首先我准备一个正常使用的完整系统。 使用Gparted软件先将母盘&#xff08;如U盘&#xff0c;TF卡&#xff09;分区调整为只有数据的大小。如&#xff1a;60G的TF卡&#xff0c;只用了3.5G&#xff0c;将未使用的空间…

doris:基于 Arrow Flight SQL 的高速数据传输链路

Doris 基于 Arrow Flight SQL 协议实现了高速数据链路&#xff0c;支持多种语言使用 SQL 从 Doris 高速读取大批量数据。 用途​ 从 Doris 加载大批量数据到其他组件&#xff0c;如 Python/Java/Spark/Flink&#xff0c;可以使用基于 Arrow Flight SQL 的 ADBC/JDBC 替代过去…

Gitee图形界面上传(详细步骤)

目录 1.软件安装 2.安装顺序 3.创建仓库 4.克隆远程仓库到本地电脑 提交代码的三板斧 1.软件安装 Git - Downloads (git-scm.com) Download – TortoiseGit – Windows Shell Interface to Git 2.安装顺序 1. 首先安装git-2.33.1-64-bit.exe&#xff0c;顺序不能搞错2. …

用公网服务代理到本地电脑笔记

参考&#xff1a; 利用frp 穿透到内网的http/https网站&#xff0c;实现对外开放&#xff08;这篇博客有点老&#xff0c;需要改动&#xff0c;不能照抄&#xff09;&#xff1a;https://www.cnblogs.com/hahaha111122222/p/8509150.html frp内网穿透(windows和服务器)&#xf…

(leetcode算法题)384. 打乱数组 398. 随机数索引

问题转化&#xff1a; 题目要求将nums中的数字出现的次序随机打乱 转化成&#xff1a;对于 0 号位置来说&#xff0c;nums[i], ..., nums[n - 1] 可以等概率的出现 ... && ... && 对于 n - 1号位置来说&#xff0c;nums[i], ..., nums[n - 1] 可以等概率的出…

Redis - 5 ( 18000 字 Redis 入门级教程 )

一&#xff1a; 补充知识 1.1 渐进式遍历 Redis 使用 scan 命令以渐进式方式遍历键&#xff0c;避免了直接使用 keys 命令可能引发的阻塞问题。scan 的时间复杂度为 O(1)&#xff0c;但需要多次执行才能完成对所有键的遍历&#xff0c;整个过程分步进行&#xff0c;有效减少阻…

22408操作系统期末速成/复习(考研0基础上手)

第一部分:计算题&#xff1a; 考察范围&#xff1a;&#xff08;标红的是重点考&#xff09; 第一章&#xff1a;CPU利用率&#xff1a; 第二章&#xff1a; 进程调度算法&#xff08;需要注意不同调度算法的优先级和题目中给出的是否可以抢占【分为可抢占和不可抢占&#xff…

AI在电子制造中的应用:预测质量控制

一、 电子制造中存在的质量问题 电子制造过程中&#xff0c;由于生产工艺复杂、材料种类繁多、生产环境要求高等因素&#xff0c;可能会出现各种质量问题。 常见质量问题如下&#xff1a; 1. 空焊 原因&#xff1a;锡膏活性较弱、钢网开孔不佳、铜铂间距过大或大铜贴小元件、…

如何通过API实现淘宝商品评论数据抓取?item_review获取淘宝商品评论

前几天一个好朋友要我帮忙抓一下淘宝商品的评论数据&#xff0c;获取淘宝评论数据可以帮忙商家们做好市场调研&#xff0c;对自己的产品进行升级&#xff0c;从而更好地获取市场。我将详细爬取方法封装成API&#xff0c;以供方便调用。 item_review-获得淘宝商品评论 响应示例…

springboot550乐乐农产品销售系统(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统乐乐农产品销售系统信息管理难度大&#xff0c;容错率低&…

百度贴吧的ip属地什么意思?怎么看ip属地

在数字化时代&#xff0c;IP地址不仅是网络设备的唯一标识符&#xff0c;更承载着用户的网络身份与位置信息。百度贴吧作为广受欢迎的社交平台&#xff0c;也遵循相关规定&#xff0c;在用户个人主页等位置展示账号IP属地信息。那么&#xff0c;百度贴吧的IP属地究竟意味着什么…

[读书日志]从零开始学习Chisel 第一篇:书籍介绍,Scala与Chisel概述,Scala安装运行(敏捷硬件开发语言Chisel与数字系统设计)

简介&#xff1a;从20世纪90年代开始&#xff0c;利用硬件描述语言和综合技术设计实现复杂数字系统的方法已经在集成电路设计领域得到普及。随着集成电路集成度的不断提高&#xff0c;传统硬件描述语言和设计方法的开发效率低下的问题越来越明显。近年来逐渐崭露头角的敏捷化设…

element-plus大版本一样,但是小版本不一样导致页面出bug

npm 的版本 node的版本 npm的源这些都一样&#xff0c;但是效果不一样 发现是element的包版本不一样导致的 2.9.1与2.8.1的源是不一样的&#xff0c;导致页面出bug;

【网络协议】开放式最短路径优先协议OSPF详解(一)

OSPF 是为取代 RIP 而开发的一种无类别的链路状态路由协议&#xff0c;它通过使用区域划分以实现更好的可扩展性。 文章目录 链路状态路由协议OSPF 的工作原理OSPF 数据包类型Dijkstra算法、管理距离与度量值OSPF的管理距离OSPF的度量值 链路状态路由协议的优势拓扑结构路由器O…

《数据结构》期末考试测试题【中】

《数据结构》期末考试测试题【中】 21.循环队列队空的判断条件为&#xff1f;22. 单链表的存储密度比1&#xff1f;23.单链表的那些操作的效率受链表长度的影响&#xff1f;24.顺序表中某元素的地址为&#xff1f;25.m叉树第K层的结点数为&#xff1f;26. 在双向循环链表某节点…

华为数通考试模拟真题(附带答案解析)题库领取

【多选题】 管理员想要更新华为路由器的VRP版本&#xff0c;则正确的方法有? A管理员把路由器配置为FTP服务器&#xff0c;通过FTP来传输VRP软件 B:管理员把路由器置为FTP客户端&#xff0c;通过FTP来传输VRP软件 C:管理员把路由器配置为TFTP客户端&#xff0c;通过TFTP来传…