Linux——线程(3)线程同步

一、线程同步的引入

通过上面的抢票系统我们发现,有的线程,进行工作(挂锁),当其马上结束工作(解锁),发现外面有很多线程在排队等着加锁执行任务,这个线程解锁后就立马给自己加锁(可以想象成自己能直到解锁的时间,所以加锁的优势比其他线程大),但是如果这个线程本身并没有做什么工作,就会使工作效率低下,线程饥饿等问题。

为了解决这个问题,我们规定:所有线程等待加锁必须排队,加锁的线程解锁后必须排在队尾等待下一次加锁,这样就能保证所有线程都可以执行任务。这就是线程同步。

二、条件变量

条件变量与互斥锁的相关接口几乎完全相同,在这里就不多介绍语法了。

但也有些新的接口。

我们用一个场景来介绍一下这些接口是怎么用的。

我们现在有一个主线程和若干个新线程(共用一个锁)

主线程负责派发任务,新线程负责执行(如果不派发就无法执行)

所以,当一个线程拿到锁进行查看时,如果发现有任务就执行,但如果发现任务还没派发,就会去某个条件变量那里进行等待(pthread_cond_wait接口),后面的线程也是如此,这里是在条件变量这的等待队列(先进先出)。在等待过程中就不会一直的申请加锁而阻止主线程派发任务了。在所有新线程等待的情况下,当主线程加锁后派发任务后,会通知(唤醒)第一个开始等待的新线程,让它去加锁执行任务(pthread_cond_signal接口),同时,主线程也可以一次唤醒多个线程,让他们去抢夺该资源(pthread_cond_broadcast接口),这便是这些接口的使用方法。

三、生产者消费者模型

对于多线程并发的情况,我们可以用生产者消费者模型来解释一下。

首先,我们把主线程称为生产者,可以视为派发任务方,然后多个新线程称为消费者,视为取得任务并执行任务。在二者之间,有一个桥梁——共享或临界资源。那么生产者就会对这份资源进行派发任务的行为,其他消费者要执行任务时,并不会直接向生产者询问索取,而是直接访问该临界资源、上锁并执行。通过这个临界资源,我们就可以讲生产和消费进行解耦了。同时,临界资源可以作为媒介,当生产者派发任务多时可以间接通知消费者并增加消费者数量,反之则减少。

而在这个模型中,我们需要研究多个生产与多个消费的同步互斥关系。

首先,生产者与生产者之间是互斥的,毕竟从现实角度考虑,我派发了就不允许你派发。

消费者与消费者之间也是互斥的,如果任务很少而线程很多时,就会出现我抢到任务了而别人都没抢到。

还有就是生产者与消费者,他们是既互斥又同步的,互斥在于,生产者在派发任务时不允许消费者进来枪任务干扰生产者,而消费者在抢任务时也不许生产者发任务干扰。同步在于,生产者派发任务时,虽然无法抢,但消费者们可以进行排队等待,而对于生产者们也是一样的。

总结就是:2个角色,3个关系,1个交易场所。

有了这个模型,我们就可以把条件变量的接口来解释了。

首先

wait就相当于创建该媒介,让线程在该阻塞队列中等待。signal就是叫醒排在最前面的一个线程执行,broadcast就是一次唤醒所有在队列的线程。

至于wait的接口为什么还要把锁传进去呢?——在线程进入等待的时候要解锁!即解锁与等待是原子性操作。

条件等待是线程间同步的⼀种手段,如果只有⼀个线程,条件不满足,⼀直等下去都不会满足, 所以必须要有⼀个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好 的通知等待在条件变量上的线程。条件不会无缘无故的突然变得满足了,必然会牵扯到共享数据的变化。所以一定要用互斥锁来保护。没有互斥锁就无法安全的获取和修改共享数据。由于解锁和等待不是原子操作。调用解锁之后, pthread_cond_wait 之前,如果已经有其他线程获取到互斥量,摒弃条件满足,发送了信号,那么 pthread_cond_wait 将错过这个信 号,可能会导致线程永远阻塞在这个 pthread_cond_wait 。所以解锁和等待必须是⼀个原子操作。

同时,被唤醒的线程也会重新申请锁。

四、信号量

什么是信号量呢?首先,信号量和信号并没有关系。

对于一块公共资源(临界区),我们可以当作一整份使用,比如我们的阻塞队列。但有时,我们也可以分成多块,然后以块为单位访问这块资源,就可以让多个执行流并发访问该块资源了。

首先,信号量是一个计数器,用来表明临界资源中的资源数目。而我们申请信号量,本质是对临界资源的预订(并非等同于使用),只要预订成功即使不使用,其他线程也无法使用。而我们信号量作为保护公共资源的机制,本身自己也属于临界资源,因此申请信号量的操作必须是原子的。此外,如果我们的计数器只有0和1,那不就成为了我们在线程互斥提到的锁了吗。

五、有关信号量的环形队列

在上面的生产者消费者模型,我们的交易场所是阻塞队列,有了信号量的引入,我们介绍一种新的交易场所模型——基于信号量的环形阻塞队列(首尾相连)。(为空或为满,都指向一个位置)

在这个队列中,任何人访问此临界资源,必须先申请信号量!对于生产者来说,在意的是剩余空间,而对于消费者来讲在意的是剩余数据。我们介绍一下此队列的两种情况

1.生产消费同时访问同一个位置

如果为空,说明队列无数据,消费者就需要阻塞等待,让生产者放入数据。

如果为满,说明队列满数据,生产者就需要阻塞等待,让消费者取得并拿出数据。这两种情况都可以保证原子性!体现了互斥同步原则。

2.指向不同位置

此时就有点像追及问题,此时生产者和消费者就可以同时进行访问临界资源,直到回到1情况再继续一方等待。这种情况就满足了并发原则。

因此,我们要设计两个信号量分别给生产消费,以让他们看到临界资源的使用情况。

六、信号量的相关接口

1.sem_init

第一个参数不说了,第二个是是否设置为线程间共享,默认设置为0即可,第三个是设置信号量的初始值。

2.sem_destroy

3. P操作(申请信号量)

申请失败就会阻塞

4.V操作(释放信号量)

提一下,假设我们现在是生产者的视角,我们就需要让空间信号量先进行P操作,等放入数据后,再让消费者(数据信号量)进行V操作。

关于P、V操作

P、V本质都是对信号量的操作,P操作就是申请信号量,预订资源(但如果信号量为负就会阻塞等待,直到有其他资源释放导致该信号量++,然后把信号量--),V操作是释放资源以及唤醒其他阻塞等待的线程,如果没有等待的线程,那么信号量的值会累加。

对于空间信号量(生产)和数据信号量(消费)而言,我们简述一下大致流程:
当要放入数据时,空间信号量会预订(P)(如果没有等待就进行插入操作),然后放完数据后,让数据信号量进行V(因为插入一个数据后导致数据个数增加,消费者对于这块空间的可访问量++)。而消费者进行消费过程正好与之相反。 (我们把信号量看成可访问资源块的数量就好理解了)

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

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

相关文章

基于go的简单管理系统(增删改查)

package mainimport ("database/sql""fmt"_ "github.com/go-sql-driver/mysql" )var db *sql.DBtype user struct {id intname stringage int }// 建立连接 func initDB() (err error) {dsn : "root:123456tcp(127.0.0.1:3306)/mysqltes…

HTN77A0原理图提供聚能芯半导体禾润一级代理技术支持免费送样

在电源管理需求日益严苛的当下,禾润 HTN77A0 以卓越性能脱颖而出。它不仅适配多种应用场景,还兼具高效节能与稳定输出,为设备供能带来革新体验。 禾润 HTN77A0 同步降压变换器,凭借5V~130V 超宽输入电压范围,打破传统供…

小程序中的页面跳转

小程序中的页面跳转 在之前网页的学习中,我们往往采用超链接,或者定义方法、函数等方式来实现页面的跳转,但是微信小程序中没有超链接,那我们该如何实现呢?微信小程序的页面跳转包括两个,一个是tabBar页面…

在K8S迁移节点kubelet数据存储目录

默认k8s节点kubelet数据目录在 /var/lib/kubelet,如果在部署前没有做好规划,其实默认就存储在系统盘/分区下了,这样会导致一个问题,如果数据量过大会导致kubelet服务异常,其次,系统盘下有一些系统服务引用&…

MySQL基础关键_002_DQL(一)

目 录 一、初始化 二、简单查询 1.部分语法规则 2.查询一个字段 (1)查询员工编号 (2)查询员工姓名 3.查询多个字段 (1)查询员工编号、姓名 (2)查询部门编号、名称、位置 …

阿里云服务迁移实战: 04-IP 迁移

普通过户 如资料过户按量付费EIP所述,如果原账号是个人账号,则目标账号无限制,如果原账号是企业账号,则目标账号必须为相同认证主体的企业账号。 其主要操作就是,在原账号发起过户,在新账号接收过户。具体…

安恒安全培训实习生,CTF方向面试题!

目均模拟真实CTF赛题,需结合动态调试与工具链(pwntools/ROPgadget/one_gadget)完成利用。 覆盖栈、堆、格式化字符串、高级堆利用、沙箱逃逸五大方向,从基础ROP到House of Apple,逐步提升对抗防护的能力。 题目1&…

【C++QT】Combo Box 组合框控件详解

文章目录 一、QComboBox(Combo Box)1. 基本用法2. 特性3. 信号与槽函数 二、QFontComboBox(Font Combo Box)1. 基本用法2. 特性3. 信号与槽函数 三、总结如果这篇文章对你有所帮助,渴望获得你的一个点赞! 在…

Best Video下载器——全能高清无水印视频下载工具

在当今短视频和流媒体盛行的时代,用户经常遇到想要下载视频却受限于平台限制的情况。无论是收藏喜欢的影视片段、保存有价值的教程,还是进行二次创作,一款高效、免费且支持多平台的视频下载工具显得尤为重要。Best Video下载器正是为此而生&a…

AI音频核爆!Kimi开源“六边形战士”Kimi-Audio,ChatGPT语音版?

音频处理领域的天花板被撕开了。 刚刚,kimi 发布全新通用音频基础模型 Kimi-Audio,这款由月之暗面(Moonshot AI)推出的开源模型,在 24 小时内收获 3.2 万星标,不仅以 1.28% 词错率刷新语音识别纪录&#xf…

安装VMware虚拟机时出现报错:

如果已在 BIOS/固件设置中禁用 Intel VT-x,或主机自更改此设置后从未重新启动,则 Intel VT-x 可能被禁用。 1.解决的方法: BIOS 设置要求 为了使 VMware Workstation 支持用户级别的监控并允许模块 MonitorMode 成功启动,需确保…

基于ESP32 S3 + PVDF采集呼吸心率

压电薄膜可以采集到微动特征,压阻传感器可以采集到是否有大重量压力,利用这个特性实现类似于床带采集呼吸心率,实现生命体征检测功能 ESP32 S3 PVDF实现生命体征检测带 硬件: ESP32 S3PVDF压敏压阻涂鸦传感器(可选支…

多模态大语言模型arxiv论文略读(五十)

Pensieve: Retrospect-then-Compare Mitigates Visual Hallucination ➡️ 论文标题:Pensieve: Retrospect-then-Compare Mitigates Visual Hallucination ➡️ 论文作者:Dingchen Yang, Bowen Cao, Guang Chen, Changjun Jiang ➡️ 研究机构: 同济大学…

智能驾驶新时代:NVIDIA高级辅助驾驶引领未来出行安全

智能驾驶新时代:NVIDIA高级辅助驾驶引领未来出行安全 在全球汽车产业数字化转型的时代潮流中,高级辅助驾驶技术已逐渐成为推动产业革新的核心动力。作为这一领域的领导者之一,NVIDIA通过其先进的技术解决方案,正在积极塑造未来的…

总结小程序的坑

小程序中的wxss中 background不能使用本地图片 解决方法: 使用 Base64 编码(适合小图片)使用网络图片, 网络图片需要用https用 image 标签替代 分包的图片主包不能使用,这是分包中的图片资源默认不能被主包或其他分包直…

供应链管理-国际结算:本币互换 / 数字货币桥 / 我国在沙特发行美债

一、本币互换 本币互换(Local Currency Swap)是指两国(或地区)的央行(货币当局)签订协议,约定在一定条件下,任何一方可以一定数量的本币交换等值的对方货币,用于双边贸易…

湖北理元理律师事务所:从法律视角看债务优化的合规实践

在债务纠纷高发的社会背景下,法律服务机构如何通过合规手段帮助债务人实现债务优化,成为公众关注的议题。湖北理元理律师事务所作为经国家司法局注册登记的债事服务机构,其服务模式与成果为行业提供了可参考的样本。 服务框架:法…

免费在Colab运行Qwen3-0.6B——轻量高性能实战

Qwen一直在默默地接连推出新模型。 每个模型都配备了如此强大的功能和高度量化的规模,让人无法忽视。 继今年的QvQ、Qwen2.5-VL和Qwen2.5-Omni之后,Qwen团队现在发布了他们最新的模型系列——Qwen3。 这次他们不是发布一个而是发布了八个不同的模型——参数范围从6亿到235…

【Java】打印运行环境中某个类引用的jar版本路径

背景 正式环境出现jar版本不匹配问题,不知道正式环境用的哪个jar版本。通过一下可以打印出类调用的jar // 获取 POIFSFileSystem 类的加载器并打印其来源路径 ClassLoader classloaderPOIFS org.apache.poi.poifs.filesystem.POIFSFileSystem.class.getClassLoade…

Python生活手册-元组:保险柜与瑞士军刀

一、元组的本质:数据世界的保险柜 Python元组就像银行金库里的​​智能保险箱​​,一旦存放物品就会自动焊死箱门。当你把结婚戒指和房产证放进保险箱后,任何人都无法替换或破坏这些物品,只能通过特定窗口查看内容。 # 创建家庭…