系统编程-同步互斥机制
1|0同步互斥机制
-
同步概念
所谓同步,即同时起步,协调一致。不同对象,对于“同步”的理解方式不一样(略有不同)。如设备同步,是指在两个设备之间规定一个共同的时间作为参考;数据同步,是指让两个或多个数据库内容保持一致,或者按需要部分保持一致;文件同步,是指两个或者多个文件夹的文件保持一致等等
但是在编程中,通信中说的同步与生活中大家印象中同步是不一样的。“同”,协同,协助,互相配合,主旨在协同步调。按照预定先后次序运行。 -
线程同步,指一个线程发出来某一个调用时,在没有得到结果之前,该调用不返回。同时其它线程为了保证数据的一致性,不能调用该功能。说白了就是线程在执行任务时有先后顺序,为了防止线程资源被抢占。“同步”的目的,是为了避免数据混乱,解决与时间有关的错误。实际上,不仅线程间需要同步,进程间,信号间等等都需要信号同步机制。
-
处理同步互斥方式有哪些
- 信号量---------->进程
- 有名信号量---------->进程
- 无名信号量---------->线程
- 互斥锁---------->线程
- 读写锁---------->线程
2|0同步互斥方式之有名信号量
- 有名信号量的特点
有名信号量与信号量非常相似,但是信号量的值只能是0/1,而有名信号量可以是0~+∞
信号量使用空间+数据来处理互斥,而有名信号量只使用数据来处理 - 有名信号量的函数接口
- 创建并打开一个有名信号量------->sem_open()
注意:如果oflag中有O_CREAT这个选项,则这个mode与value必须要填
- 有名信号量的P操作
- P操作:资源数-1操作------->sem_wait()
- 有名信号量的V操作
- V操作:资源数+1操作------->sem_post()
- 关闭有名信号量--------sem_close()
- 删除有名信号量--------sem_unlink()
实操(有名信号量+共享内存):
写端
读端
3|0同步互斥方式之无名信号量
- 什么是无名信号量
一般作用于线程之间的互斥,由于是无名信号量,所以是没有名字的,不能用sem_open()打开 - 无名信号量的函数接口
- 定义一个无名信号量
sem_t sem-------无名信号不是一个文件,是一个变量 - 初始化一个无名信号量------>sem_init()
3.无名信号量的操作
- P操作:资源数-1操作------->sem_wait()
- 无名信号量的V操作
- V操作:资源数+1操作------->sem_post()
- 销毁无名信号量--------sem_destroy()
练习1:有一个进程,创建5个线程出来,每一个线程任务都是一样的
任务:将"helloworld"每隔1s打印一个字符。-->10s
练习2:有一个进程,创建5个线程出来,每一个线程任务都是一样的(使用无名信号量去处理同步互斥)
任务:将"helloworld"每隔1s打印一个字符。-->10s
- 练习1
- 练习2
stdout和stderr都是标准输出到屏幕,stdout是有缓冲区的,stderr是没有缓冲区的
4|0同步互斥方式之互斥锁
- 什么是互斥锁
- 互斥锁是专门用于处理线程互斥的一种方式,它有两种状态:上锁状态/解锁状态。如果互斥锁处于上锁状态,那么再上锁会阻塞,知道这把锁解开之后,才能上锁。解锁状态依然继续解锁,不会阻塞
- 注意
- 同一时刻,只有一个线程持有该锁
- 当线程A对某一全局变量加锁访问,线程B在访问前尝试加锁,会拿不到锁,线程B阻塞。一个线程C不去加锁,直接去访问该全局变量,依然可以访问,但会出现数据混乱
- 所以,互斥锁实际上给操作系统提供了一把“建议锁“(又称“协同锁”),建议程序中有多线程访问共享资源的使用该机制。但是没有强制限定。因此即使有了mutex锁,如果有线程不按规则来访问数据,依然会造成数据踩踏
- 关于线程互斥锁函数接口
- 定义互斥锁变量----->pthread_mutex_t
pthread_mutex_t mutex
pthread_mutex_t
类型,其本质是一个结构体。 - 初始化互斥锁------>
pthread_mutex_init()
- 上锁------>
pthread_mutex_lock()
- 解锁------>int pthread_mutex_unlock()
- 销毁------>int pthread_mutex_destroy()
-
lock和unlock
lock尝试加锁,如果加锁不成功,线程阻塞,阻塞到持有该互斥量的其它线程解锁为止。unlock主动解锁函数,同时将阻塞在该锁上的所有线程全部唤醒,至于哪个线程先被唤醒,取决于优先级,调度。默认是谁先被阻塞,谁先被唤醒
例如:P1,P2,P3,P4使用一把mutex锁。P1加锁成功,其他线程都阻塞,直到P1解锁。P1解锁后,P2,P3,P4均被唤醒,并自动
再次尝试加锁。
可以理解为:mutex锁init成功初值为1。lock功能是将mutex--。而unlock则将mutex++; -
lock和trylock
lock加锁失败会阻塞,等待锁释放。trylock加锁失败会直接返回错误号(如:EBUSY)
实操
5|0死锁
- 线程试图对同一互斥量加锁两次
- 线程1拥有A锁,请求获得B锁;线程2拥有B锁,请求获得A锁
__EOF__

本文链接:https://www.cnblogs.com/bcc0729/p/17669120.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」