Linux——信号量

什么是信号量?

信号量是用来用于同步和互斥的。其实就是一个计数器进行PV操作,其中P操作就是让计数器–,V操作就是让计数器++。

从物理上说明信号量的P、V操作的含义。 P(S)表示申请一个资源,S.value>0表示有资源可用,其值为资源的数目;S.value=0表示无资源可用;S.value<0, 则|S.value|表示S等待队列中的进程个数。V(S)表示释放一个资源,信号量的初值应该大于等于0。P操作相当于“等待一个信号”,而V操作相当于“发送一个信号”,在实现同步过程中,V操作相当于发送一个信号说合作者已经完成了某项任务,在实现互斥过程中,V操作相当于发送一个信号说临界资源可用了。实际上,在实现互斥时,P、V操作相当于申请资源和释放资源。

信号量通常用于生产者消费者模型

进程互斥

  • 由于各进程的要求共享资源,而且有些资源互斥使用,因此各进程之间竞争使用这些资源,进程的这种关系就叫做互斥
  • 系统中某些资源一次只允许一个进程使用,称这样的进程资源为临界资源或互斥资源
  • 在进程中涉及到的互斥资源叫做临界区。

进程同步

进程同步是指在多个并发执行的进程之间协调和控制它们的执行顺序,以及管理它们对共享资源的访问,以避免竞态条件(Race Condition)和数据不一致性等并发问题。在多任务操作系统中,进程同步是一个关键的概念,确保进程能够正确地协同工作而不会产生意外的结果。

现在有这样一个场景,看电影
看电影一定要有位置(资源),只有当我们买了票,我们就拥有了这个位置(此时相当于P操作),资源会减少一个,当我们观看完电影,我们就会离开。这时位置就不属于你了(此时就是V操作)。
所以我们就有了以下的信息:
1.申请信号量的本质:让信号量计数器–
2.主要申请信号量成功,临界资源内部,一定会给你预留了你想要的资源——申请信号量的本质其实就是对临界区资源的预定机制

相关接口

信号量的初始化

在这里插入图片描述
sem:自己定义的信号量变量
pshared:0表示线程间的共享,非0表示进程间共享
value:信号量初始值(资源数)

信号量的销毁

在这里插入图片描述

信号量的等待

在这里插入图片描述
等待信号量,其实就是P操作,将计数器–

信号狼的发布

在这里插入图片描述
其实就是信号量的V操作,将计数器++

基于环形队列的生产者消费者模型

环形队列其实本质上不是一个真正的环形, 它其实本质是一个数组。
之所以是环形,是我们将它抽象了出来,更好的理解。

环形队列里面的内容就是我们要访问的临界资源,我们的生产者和消费者可能会同时访问同一个资源。
这时有两种情况:
1.资源为空,这种情况没有资源了,消费者就无法访问,就应该阻塞
2.资源为满,生产者不应该生产,阻塞
在这里插入图片描述

在这里插入图片描述

其他情况就是生产者和消费者在不同的临界资源生产和消费。

因为生产者和消费者是并发指向的,所以我们就需要保证同步和互斥。

所以,我在这里设置了2个信号量,一个代表了空间资源,一个代表了数据资源。当空间资源为满的时候,生产者就不应该生产,反之数据资源也一样。

//将sem封装了起来
class Sem
{
public:Sem(int value){//为0代表着多线程的同步,值大于0表示可以共享,用于多个相关进程的同步sem_init(&sem_,0,value);}~Sem(){sem_destroy(&sem_);}void p(){//申请信号量资源,如果申请失败,就阻塞sem_wait(&sem_);}void v(){//信号量本质就是一个计数器,这个函数就是让计数器++sem_post(&sem_);}private:sem_t sem_;
};
const int g_default_num = 5;template <class T>
class RingQueue
{
public:RingQueue(int default_num = g_default_num): ring_queue_(default_num), num_(default_num), c_step(0), p_step(0), space_sem_(default_num), data_sem_(0){pthread_mutex_init(&clock, nullptr);pthread_mutex_init(&plock, nullptr);}~RingQueue(){pthread_mutex_destroy(&clock);pthread_mutex_destroy(&plock);}//这里注意是先去进行P操作,再去加锁void push(const T &in){space_sem_.p();pthread_mutex_lock(&plock);ring_queue_[p_step++] = in;p_step %= num_;pthread_mutex_unlock(&plock);data_sem_.v();}void pop(T *out){data_sem_.p();pthread_mutex_lock(&clock);*out = ring_queue_[c_step++]; // pop数据后,生产者就多了一个资源c_step %= num_;pthread_mutex_unlock(&clock);space_sem_.v();}private:std::vector<T> ring_queue_;int num_;              // 有多少空间int c_step;            // 消费者下标int p_step;            // 生产者下标Sem space_sem_;        // 空间资源Sem data_sem_;         // 数据资源pthread_mutex_t clock; // 消费者的锁pthread_mutex_t plock; // 生产者的锁
};
void *consumer(void *args)
{RingQueue<int> *rq = (RingQueue<int> *)args;while (1){sleep(1);int x;rq->pop(&x);// 进行一定的处理 -- 不要忽略它的时间消耗问题std::cout << "消费: " << x << " [" << pthread_self() << "]" << std::endl;}
}void *productor(void *args)
{RingQueue<int> *rq = (RingQueue<int> *)args;while (1){int x = rand() % 100 + 1;rq->push(x);std::cout << "生产: " << x << " [" << pthread_self() << "]" << std::endl;}
}int main()
{srand((uint64_t)time(nullptr));RingQueue<int> *rq = new RingQueue<int>();pthread_t c[5], p[3]; // 生产者和消费者for (int i = 0; i < 5; i++){pthread_create(&c[i], nullptr, consumer, (void *)rq);}for (int i = 0; i < 3; i++){pthread_create(&p[i], nullptr, productor, (void *)rq);}for (int i = 0; i < 5; i++){pthread_join(c[i], nullptr);}for (int i = 0; i < 3; i++){pthread_join(p[i], nullptr);}return 0;
}

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

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

相关文章

OBS插件--复合模糊

复合模糊 复合是一款滤镜插件&#xff0c;支持多种模糊类型和多种蒙版效果。支持模糊源的部分显示区域&#xff0c;可以反选区域进行模糊&#xff0c;这个功能对于场景部分区域需要遮盖非常实用。 下面截图演示下操作步骤&#xff1a; 首先&#xff0c;打开 OBS直播助手 在…

实现用户个人随机salt生成jwt及鉴别用户权限的实现思路

实现用户个人随机salt生成jwt及鉴别用户权限的实现 盐值是什么&#xff1f; 盐值&#xff08;salt&#xff09;是在密码学中用于增加密码安全性的一种随机值。它通常是一个随机生成的字符串&#xff0c;与用户密码结合在一起&#xff0c;然后再进行加密处理。盐值的作用是增加…

【Unity 鼠标输入检测】

Unity 鼠标输入检测 Unity提供了多种方法来检测和处理鼠标输入&#xff0c;允许开发者在游戏中实现对鼠标移动、点击和滚轮滚动的响应。以下是一些基本的鼠标输入检测方法&#xff1a; 1. Input.mousePosition 这个属性返回当前鼠标指针的屏幕坐标。坐标是以像素为单位的&…

【吊打面试官系列】Java高并发篇 - 同步方法和同步块,哪个是更好的选择?

大家好&#xff0c;我是锋哥。今天分享关于 【同步方法和同步块&#xff0c;哪个是更好的选择&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 同步方法和同步块&#xff0c;哪个是更好的选择&#xff1f; 同步块是更好的选择&#xff0c;因为它不会锁住整个对象…

Prim算法(Prim‘s Algorithm)

Prim算法&#xff08;Prims Algorithm&#xff09;&#xff0c;由罗伯特普里姆&#xff08;Robert C. Prim&#xff09;于1957年提出&#xff0c;是一种用于构造加权无向图的最小生成树&#xff08;Minimum Spanning Tree, MST&#xff09;的贪心算法。最小生成树是一个无环子图…

临近空间相关概念

临近空间概念 距地 20KM-100KM 的临近空间位于内外层空间之中&#xff0c;也称为 超高空、近空间、亚轨道等。 特点就是&#xff1a;纵跨 非电离层和电离层、空气稀薄&#xff0c;存在 臭氧、紫外、辐射等特殊环境 存在 重力波、行星波、大气放电等特殊现象。 临近空间高速飞…

##15 探索高级数据增强技术以提高模型泛化能力

文章目录 前言数据增强的重要性常见的数据增强技术高级数据增强技术在PyTorch中实现数据增强结论 前言 在深度学习领域&#xff0c;数据增强是一种有效的技术&#xff0c;它可以通过在原始数据上应用一系列变换来生成新的训练样本&#xff0c;从而增加数据的多样性&#xff0c…

前端 | 易混词卡片切换

文章目录 &#x1f4da;实现效果&#x1f4da;模块实现解析&#x1f407;html&#x1f407;css&#x1f407;javascript &#x1f4da;实现效果 绘制单词卡片效果&#xff0c;实现点击左半部分上翻&#xff0c;点击右半部分下翻。 &#x1f4da;模块实现解析 &#x1f407;…

品鉴中的个人风格:如何形成自己与众不同的红酒品鉴体验

品鉴云仓酒庄雷盛红酒不仅是一种感官体验&#xff0c;更是一种个人风格的展现。每个人都有自己与众不同的品味和偏好&#xff0c;通过品鉴红酒&#xff0c;我们可以形成自己与众不同的红酒品鉴体验。 要形成自己与众不同的红酒品鉴体验&#xff0c;首先需要勇于尝试不同类型的红…

conda 常用20个命令

conda常用20个命令 这些命令涵盖了Conda环境管理和包管理的常用功能&#xff0c;可帮助你有效地管理Python环境和软件包。 创建环境&#xff1a; conda create --name myenv这个命令用于创建一个名为myenv的新环境。你可以在--name后面指定环境的名称&#xff0c;并在其后加上…

C++语法之在谈const与模版参数

最近一直在复习C的语法&#xff0c;感觉遇到了不少问题&#xff0c;或许是之前没想的这么深。废话不说&#xff0c;开始说正事。 一、再谈const 有些朋友可能有些疑问&#xff0c;不就是const吗&#xff1f;我知道&#xff0c;const可以给非const赋值&#xff0c;反过来不行&…

通过mvn archetype 创建一个spring boot start 工程

mvn archetype https://maven.apache.org/archetype/index.html 遇到的问题 对于想自定义一个spring-boot-start的同学,比如 Springboot自定义Starter启动器 整个过程很繁琐。 定义属性开关增加 spring boot test start插件定义自动装载 spring.factories or org.springfra…

Webpack模块联邦:微前端架构的新选择

Webpack模块联邦&#xff08;Module Federation&#xff09;是Webpack 5引入的一项革命性特性&#xff0c;它彻底改变了微前端架构的实现方式。模块联邦允许不同的Web应用程序&#xff08;或微前端应用&#xff09;在运行时动态共享代码&#xff0c;无需传统的打包或发布过程中…

javax.net.ssl.SSLException: Received fatal alert: protocol_version已经解决

起因&#xff1a; 在帮别人讲解项目时&#xff0c;将项目的tomcat配置完&#xff0c;点击运行后&#xff0c;报错&#xff0c;信息如标题。 解决办法&#xff1a; 在csdn百度问题&#xff0c;得到的方法主要有几个&#xff1a; 1.jdk要配置在1.8以上&#xff1b; 2.数据库地…

Stable Diffusion是什么?

目录 一、Stable Diffusion是什么&#xff1f; 二、Stable Diffusion的基本原理 三、Stable Diffusion有哪些运用领域&#xff1f; 一、Stable Diffusion是什么&#xff1f; Stable Diffusion是一个先进的人工智能图像生成模型&#xff0c;它能够根据文本描述创造出高质量的图…

Spring IOC容器加载流程原理源码深度剖析

Spring IOC容器加载流程原理源码深度剖析 介绍 在Java开发中&#xff0c;Spring框架是非常常用的一个框架&#xff0c;它提供了很多便捷的功能和特性&#xff0c;其中最重要的就是IOC&#xff08;Inversion of Control&#xff09;容器。Spring IOC容器是Spring框架的核心&am…

邻接矩阵基础入门

引言 邻接矩阵是图论中表示图的一种方式&#xff0c;它通过矩阵来描述图中各顶点之间的连接关系。在邻接矩阵中&#xff0c;图中的每个顶点都对应矩阵中的一行和一列&#xff0c;矩阵中的元素表示顶点之间是否存在边以及边的权重&#xff08;如果是加权图&#xff09;。 定义和…

什么是ip地址?和dns地址的区别是什么?

大家都知道电脑想要上网需要配置ip地址和dns地址&#xff0c;手动配置、自动获取均可&#xff0c;但是ip地址是什么&#xff1f;和dns又有什么区别呢&#xff1f;小编给大家详细解释一下。 IP地址 IP,就是Internet Protocol的缩写&#xff0c;是一种通信协议&#xff0c;我们用…

信息检索(36):ConTextual Masked Auto-Encoder for Dense Passage Retrieval

ConTextual Masked Auto-Encoder for Dense Passage Retrieval 标题摘要1 引言2 相关工作3 方法3.1 初步&#xff1a;屏蔽自动编码3.2 CoT-MAE&#xff1a;上下文屏蔽自动编码器3.3 密集通道检索的微调 4 实验4.1 预训练4.2 微调4.3 主要结果 5 分析5.1 与蒸馏检索器的比较5.2 …

Flink面试整理-了解如何对Flink进行扩展和定制化开发,以满足特定的业务需求

Apache Flink 是一个灵活且可扩展的流处理框架,允许进行定制化开发以满足特定的业务需求。以下是对 Flink 进行扩展和定制化开发的几个主要方向: 1. 自定义算子(Operators) Flink 允许开发者编写自定义算子来实现特定的数据处理逻辑。例如,可以通过扩展 RichMapFunction 或…