【Linux系统】信号量实现同步和互斥

一.回顾

在这之前已经讲解了System V版本的信号量,主要内容为以下3点:

  1. 信号量本质是一把计数器
  2. 申请信号量本质就是预订资源
  3. PV操作(申请和释放)是原子的

今天我们要学习的是POSIX版本的信号量,以上三点同样遵循

二.信号量VS互斥锁

1.联系:

信号量和互斥锁都是保护公共资源的手段,想要通过临界区访问临界资源,必须先要申请信号量或者互斥锁。并且计数器为1的信号量功能等同于互斥锁。

2.区别:

  1. 互斥锁将公共资源当成一个整体使用,信号量可以实现把公共资源分成若干区域,给不同的执行流同时使用。
  2. 申请锁成功,线程进来后一般还要使用如if这样的判断语句,来检测资源是否就绪,如果没有就绪,为了并发的高效,还需要等待条件变量。(进电影院之后再现场买票)。但是申请信号量成功,线程进来之后无需判断资源是否就绪,因为只要申请信号量成功,说明一定有资源分配给你,并且这份资源只有你自己能访问。(提前买电影票)
  3. 互斥锁在信号量都在pthread库中,不过互斥锁声明在<pthread.h>头文件,信号量声明在<semaphore.h>中

线程使用信号量流程:

申请信号量->访问指定区域->释放信号量

三.信号量用法

1.初始化信号量

sem是定义的信号量。pshared指定信号量是否进程共享,为0则线程共享,非0则进程共享。value则是计数器的初始值,表示想把公共资源分成多少份使用

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

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

4.销毁信号量

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

1.生产消费过程

生产者和消费者在环形队列的生产消费过程:

  1. 生产者不能把消费者套一个圈
  2. 消费者不能超过生产者
  3. 生产者和消费者只有两种场景会指向同一个位置:队列为空和为满

只要生产者和消费者不指向同一个位置,就可以多线程并发访问环形队列。如果为空,只能让生产者跑,如果为空,只能让消费者先跑。"只能"表现出的是互斥,"先"表现出的是同步。所以基于环形队列的生产者消费者模型,也有同步和互斥,但这种同步和互斥是局部性的,只有队列为空为满时才需要维持,这样就实现了生产和消费的并发。

2.信号量设计

生产者认为空间是资源,消费者认为数据是资源,所以分别为生产者和消费者设计条件变量,来表示空间和数据的数量。

初始时,生产者的信号量是n,消费者的信号量是0。
伪代码:

//1.初始化

p->sem_space = N;

c->sem_data = 0;

//2.生产者

P(sem_space)

//生产行为,位置待定

V(sem_data)

//3.消费者

P(sem_data)

//消费行为,位置待定

V(sem_space)

3.多生产和多消费

以上的两个信号量可以保证生产者和消费者之间的同步和互斥。如果是多个生产者和消费者,信号量能否保证生产者之间,消费者之间的互斥关系呢?

不能!因为生产者共用同一个_p_step,消费者共用同一个_c_step,读写位置的安全无法保证,也就不能保证多线程访问的是不同的位置,所以需要设计两个锁,分别对_p_step和_c_step进行保护。

相关推荐
w139548564227 分钟前
AI 周报卡片:智能生成内容的 UI 呈现
后端
全堆鸿蒙8 分钟前
天气药丸标签:Row + Text 组合实现品牌药丸
后端
sycmancia10 分钟前
Qt——另一种创建线程的方式
开发语言·qt
HONG````21 分钟前
HarmonyOS ArkUI Slider 与 Rating 实战:音量控制、亮度调节与星级评分
后端
hdsoft_huge27 分钟前
SpringBoot系列18:SpringSecurity登录鉴权,JWT无状态Token认证完整流程(生产级落地)
java·spring boot·后端
Csvn41 分钟前
📊 SQL 入门 Day 5:GROUP BY & HAVING — 开始分组分析
后端·sql
你怎么知道我是队长44 分钟前
JavaScript 函数 this 全解
开发语言·javascript·ecmascript
l134062082351 小时前
空状态引导设计:Text + Button 组合与交互反馈
后端
L-影1 小时前
单体项目结构
java·开发语言
2501_918582371 小时前
月统计面板:日记数 + 连续天数 + 主要心情
后端