互斥锁、条件变量、信号量以及适用场景

文章目录

    • 互斥锁
      • 互斥锁实战过程中常用方法
    • 条件变量
      • 条件变量实战过程中常用方法
    • 信号量
      • 信号量的常用方法
    • 生产者和消费者问题
      • 一个粗略版本的生产者消费者代码(如果只使用了互斥锁)
      • 一个改进版本的生产者消费者代码(使用了互斥锁和条件变量)
      • 一个最终版本的生产者消费者代码(使用了互斥锁和信号量)
    • 总结

互斥锁

互斥锁主要是用在多线程编程时,多个线程同时访问同一个变量的情况下,保证在某个时刻只能有一个线程访问。每个线程在访问共享变量的时候,首先要先获得锁,然后才能访问共享变量,当一个线程成功获得锁时,其他变量都会阻塞在获取锁这一步,直到这个线程释放掉锁。

互斥锁实战过程中常用方法

pthread_mutex_t mutex;//创建一个互斥量
pthread_mutex_init(&mutex,NULL); //初始化锁
pthread_mutex_lock(&mutex); //在需要上锁的片段加锁
pthread_mutex_unlock(&mutex); //在需要去锁的片段去锁
pthread_mutex_destroy(&mutex);//锁用完之后销毁锁

条件变量

条件变量的作用是用于多线程之间的线程同步。线程同步是指线程间需要按照预定的先后顺序进行的行为,比如我想要线程1完成了某个步骤之后,才允许线程2开始工作,这个时候就可以使用条件变量来达到目的。

条件变量实战过程中常用方法

pthread_cond_t cond;//创建条件变量
pthread_cond_init(&cond,NULL);//初始化条件变量
pthread_cond_signal(&cond);//通常搭配wait函数用,向条件变量发送唤醒信号
pthread_cond_wait(&cond,&mutex);//先阻塞,直至接收到signal或者broadcast后被唤醒
pthread_cond_destroy(&cond);//使用完之后销毁条件变量

信号量

信号量可以用于解决多线程环境中的竞争条件和协调线程的执行顺序

信号量的常用方法

int sem_init(sem_t *sem,int pshared,unsigned int value);//作用:初始化信号量 参数 pshared:0 用在线程间 非0 用在进程间
int sem_wait(sem_t *sem);//对信号量的值减1,如果值为0 就阻塞
int sem_post(sem_t *sem);//对信号量解锁,调用一次对信号量的值+1
int sem_destroy(sem_t *sem);//释放资源

生产者和消费者问题

生产者(Producers):生产者进程或线程的任务是生成某种类型的数据或物品,并将其放入共享缓冲区。生产者可能会生成多个数据项,并且在放置数据到缓冲区时需要确保缓冲区未满。
消费者(Consumers):消费者进程或线程的任务是从共享缓冲区中取出数据项并进行处理或消耗。消费者可能会以一定的速度获取数据,需要确保缓冲区不为空。
共享缓冲区(Buffer):这是生产者和消费者之间的共享数据结构,用于存储生产者生成的数据项。缓冲区的容量是有限的,生产者在缓冲区已满时需要等待,消费者在缓冲区为空时需要等待。

一个粗略版本的生产者消费者代码(如果只使用了互斥锁)

//生产者部分代码
void * producer(void * arg){//生产者不断的生产//不断的创建新的结点while(1){pthread_mutex_lock(&mutex);struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));newNode ->next =head;head = newNode;newNode ->num = rand()%1000;printf("add node,num:%d,tid:%ld\n",newNode->num,pthread_self());pthread_mutex_unlock(&mutex);usleep(100);}return NULL;
}
void * customer(void * arg){//消费者不断的消费数据while(1){pthread_mutex_lock(&mutex);if(head){//如果有数据struct Node * tmp =head;head = head->next;printf("del node,num:%d,tid:%ld\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);    usleep(100);            }else{pthread_mutex_unlock(&mutex);}               }return NULL;
}

虽然用了互斥锁,实现了生产者的若干个线程和消费者若干个线程互斥访问,但是如果消费者线程抢到锁之后没有资源可供消耗的话,会空转消耗cpu,抢占到锁没有用

一个改进版本的生产者消费者代码(使用了互斥锁和条件变量)

void * producer(void * arg){//生产者不断的生产//不断的创建新的结点while(1){pthread_mutex_lock(&mutex);struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));newNode ->next =head;head = newNode;newNode ->num = rand()%1000;printf("add node,num:%d,tid:%ld\n",newNode->num,pthread_self());pthread_cond_signal(&cond);pthread_mutex_unlock(&mutex);usleep(100);}return NULL;
}
void * customer(void * arg){//消费者不断的消费数据while(1){pthread_mutex_lock(&mutex);if(head){//如果有数据struct Node * tmp =head;head = head->next;printf("del node,num:%d,tid:%ld\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);    usleep(100);            }else{//如果没有数据,需要等待,阻塞了,直到生产者执行了pthread_cond_signal(&cond)才会唤醒      pthread_cond_wait(&cond,&mutex);//这个函数起两个作用,//1.是先释放mutex让执行其他代码//2.是直到pthread_cond_signal 或 pthread_cond_broadcast执行后唤醒该函数同时重新加锁//阻塞解除后要释放锁pthread_mutex_unlock(&mutex);  }}return NULL;
}

上述方法已经解决了在生产者还未生产资源的时候,cpu空转的情况。在代码中,使用了条件变量,当未生产资源时候,消费者会阻塞在pthread_cond_wait(&cond,&mutex);当生产者调用pthread_cond_signal(&cond)才会唤醒消费者继续执行,不会跟生产者抢占锁!
但是未考虑容量有限的情况,也就是说生产者能一直生产

一个最终版本的生产者消费者代码(使用了互斥锁和信号量)

void * producer(void * arg){//生产者不断的生产//不断的创建新的结点while(1){sem_wait(&psem);//调用一次先判断是否为0 为0阻塞 不为0值减1 //不能放到锁里面 假如放到锁里面 抢到锁之后,阻塞到wait,就永远死锁了//wait可以通过另一个线程的post解除锁//加互斥锁之后只能通过自身的代码解除pthread_mutex_lock(&mutex);struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));newNode ->next =head;head = newNode;newNode ->num = rand()%1000;printf("add node,num:%d,tid:%ld\n",newNode->num,pthread_self());pthread_mutex_unlock(&mutex);sem_post(&csem);//表示消费者有一个可以去消费usleep(100);}    return NULL;
}
void * customer(void * arg){//消费者不断的消费数据while(1){sem_wait(&csem);//先判断是否为0 为0阻塞 不为0消耗一个csempthread_mutex_lock(&mutex);struct Node * tmp =head;head = head->next;printf("del node,num:%d,tid:%ld\n",tmp->num,pthread_self());free(tmp);pthread_mutex_unlock(&mutex);   sem_post(&psem); //增加一个生产的位置usleep(100);                    }return NULL;
}

最终版本通过信号量实现了线程间同步,同时也可以做到有限的缓冲区容量,并且不会死锁,必须将信号量放置在互斥锁之前!!!

总结

互斥锁实现线程间互斥访问某一片段,实现了线程的互斥访问,同一时刻只能一个拿锁!
条件变量通常搭配互斥锁使用,目的是实现线程间的按一定顺序访问,即线程同步。
信号量通过消费者和生产者持有资源的变化动态调整。当生产一个产品,意味着多了一个可消耗的产品。当消耗一个产品,意味着可以再生产一个产品。

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

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

相关文章

options.css 内容优化2 --chatPGT

问&#xff1a; options.css 内容优化,功能列表的li,设置成点击按钮的样式&#xff0c;需要有鼠标经过高亮&#xff0c;选中时按钮背景颜色和未选中时的背景色需要有肉眼可见的色差 gpt: 为了使左侧功能列表的每个 <li> 元素看起来像按钮&#xff0c;并且在鼠标经过时…

机械臂抓取的产业落地进展与思考

工业机械臂是一种能够模拟人类手臂动作的机械装置&#xff0c;具有高精度、高速度和高灵活性的特点。近年来&#xff0c;随着人工智能和机器人技术的快速发展&#xff0c;机械臂在工业生产、物流仓储、医疗护理等领域得到了广泛应用。机械臂抓取技术作为机械臂的核心功能之一&a…

广东省科学技术厅关于2023年度广东省科学技术奖提名工作的通知

粤科函区字〔2023〕1290号 各有关单位&#xff08;专家&#xff09;&#xff1a; 科技奖励制度是党和政府长期坚持的一项重要科技制度&#xff0c;为深入实施创新驱动发展战略&#xff0c;加快建设更高水平的科技创新强省和粤港澳大湾区国际科技创新中心&#xff0c;进一步体现…

tp5访问的时候必须加index.php,TP5配置隐藏入口index.php文件

PS&#xff1a;这里说的入口文件指的是public/index.php,配置文件就在这个目录下 可以去掉URL地址里面的入口文件index.php&#xff0c;但是需要额外配置WEB服务器的重写规则。 以Apache为例&#xff0c;需要在入口文件的同级添加.htaccess文件(官方默认自带了该文件)&#x…

基于Keil a51汇编 —— MPL 宏定义

MPL 宏 Ax51汇编程序支持的宏处理语言&#xff08;MPL&#xff09;是一种字符串替换工具&#xff0c;使您能够编写可修复的代码块&#xff08;宏&#xff09;并将其插入源文本中的一个或多个位置。 宏处理器查看源文件的方式与汇编程序不同。 对于汇编程序来说&#xff0c;源…

UniAD 论文学习

一、解决了什么问题&#xff1f; 当前的自动驾驶方案大致由感知&#xff08;检测、跟踪、建图&#xff09;、预测&#xff08;motion、occupancy&#xff09;和规划三个模块构成。 为了实现各种功能&#xff0c;智驾方案大致包括两种路线。一种是针对每个任务都部署一个模型&a…

Python Parser 因子计算性能简单测试

一直以来&#xff0c;Python 都在量化金融领域扮演着至关重要的角色。得益于 Python 强大的库和工具&#xff0c;用户在处理金融数据、进行数学建模和机器学习时变得更加便捷。但作为一种解释性语言&#xff0c;相对较慢的执行速度也限制了 Python 在一些需要即时响应的场景中的…

读取 yaml 文件

一、引入依赖 <dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>1.32</version> </dependency> 二、读取yaml内容工作代码 &#xff08;1&#xff09;上传yaml文件 读取yaml文件并校验…

知识图谱系列3:读论文-《中国鸟类领域知识图谱构建与应用研究》-面向知识图谱的智能服务研究(需求、管理、查询、推理)

5.1鸟类领域知识服务需求研究 本部分根据不同人群&#xff0c;对其需求进行了研究。 并总结需求类型如下。 知识型服务需求指用户学习鸟类相关知识&#xff0c;包括知识内容、知识学习等。知识内容 需求为构建鸟类领域知识库作为知识的来源&#xff1b;知识学习需求为用户通过…

gici-open示例数据运行(ground_truth坐标的转换)

1. 坐标系转换说明 涉及的两个坐标转换&#xff1a; nmea_pose_to_pose &#xff1a;激光IMU中心到数据集IMU中心&#xff0c;主要是杆臂误差&#xff0c;转换关系为&#xff1a; //坐标转换的主要步骤(若发现有错误的地方&#xff0c;请评论指出) //定义激光IMU和数据集IMU之…

好看的机制示意图绘制教程汇总

好看的机制示意图绘制教程汇总 蛋白翻译过程示意图&#xff0c;特别是其中的核糖体&#xff0c;需要很多绘制技巧。主要使用椭圆工具绘制两个椭圆&#xff0c;二者组合后使外形接近核糖体。接着通过路径查找器的合并功能&#xff08;并集&#xff09;将两个椭圆合并在一起。使…

使用HHDBCS管理MongoDB

1 连接MongoDB 打开HHDBCS&#xff0c;在数据库类型中选择mongodb&#xff0c;填入相关信息&#xff0c;点击“登陆”即可。 也可以使用SSH通道进行登陆。 2 命令窗口 点击命令窗口&#xff0c;可以对数据库发出指令。 可以根据个人习惯&#xff0c;对命令窗口进行设置…

矩阵的相似性度量的常用方法

矩阵的相似性度量的常用方法 1&#xff0c;欧氏距离 欧式距离是最易于理解的一种距离计算方法&#xff0c;源自欧式空间中两点间的距离公式。 (1)二维平面上的点 a ( x 1 , y 1 ) a(x_1,y_1) a(x1​,y1​)和点 b ( x 2 , y 2 ) b(x_2,y_2) b(x2​,y2​)的欧式距离为 d ( x …

uni-app:引入echarts(使用renderjs)

效果 代码 <template><view click"echarts.onClick" :prop"option" :change:prop"echarts.updateEcharts" id"echarts" class"echarts"></view> </template><script>export default {data()…

旅游网站HTML

代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>旅游网</title> </head> <body><!--采用table编辑--> <!--最晚曾table,用于整个页面那布局--><table width&q…

Linux Ftrace介绍

文章目录 一、简介二、内核函数调用跟踪参考链接&#xff1a; 一、简介 Ftrace 是 Linux 官方提供的跟踪工具&#xff0c;在 Linux 2.6.27 版本中引入。Ftrace 可在不引入任何前端工具的情况下使用&#xff0c;让其可以适合在任何系统环境中使用。 Ftrace 可用来快速排查以下相…

0基础学习VR全景平台篇 第105篇:调色原理和色彩分析

“我心藏瑰宝灿烂如歌&#xff0c;唯有画作可为我吟唱。” 绘画、摄影、音乐等一切艺术&#xff0c;皆如是&#xff0c;敬梵高。 本节教程邀请李小岩老师讲授&#xff0c;大家欢迎&#xff01; 大家好&#xff01;欢迎收看我们这一节的课程&#xff0c;我们这一节呢主要讲的是…

川西旅游网系统-前后端分离(前台vue 后台element UI,后端servlet)

前台&#xff1a;tour_forword: 川西旅游网前端----前台 (gitee.com) 后台&#xff1a;tour_back: 川西旅游网-------后台 (gitee.com) 后端 &#xff1a;tour: 川西旅游网------后端 (gitee.com)

python对excel数据表进行数据清洗

当拿到excel表&#xff0c;使用python对excel操作前&#xff0c;第一件事情是对excel表的数据进行数据清洗。 数值是否有空值&#xff0c;是否有重复的数据&#xff0c;把以上2个问题解决完成以后&#xff0c;才是对数据真正操作的开始。 1、使用pandans读取数据 2、判断exce…

基于Springboot实现房屋租赁租房平台系统项目【项目源码+论文说明】分享

基于Springboot实现房屋租赁租房平台系统演示 摘要 在网络高速发展的时代&#xff0c;众多的软件被开发出来&#xff0c;给用户带来了很大的选择余地&#xff0c;而且人们越来越追求更个性的需求。在这种时代背景下&#xff0c;房东只能以用户为导向&#xff0c;所以开发租房网…