【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进行保护。

相关推荐
武子康22 分钟前
Java-72 深入浅出 RPC Dubbo 上手 生产者模块详解
java·spring boot·分布式·后端·rpc·dubbo·nio
冰橙子id1 小时前
linux-远程访问管理(sshd,scp,sftp)
linux·网络·ssh
还债大湿兄1 小时前
《C++内存泄漏8大战场:Qt/MFC实战详解 + 面试高频陷阱破解》
c++·qt·mfc
光电的一只菜鸡2 小时前
ubuntu之坑(十五)——设备树
linux·数据库·ubuntu
椰椰椰耶2 小时前
【Spring】拦截器详解
java·后端·spring
brzhang3 小时前
我操,终于有人把 AI 大佬们 PUA 程序员的套路给讲明白了!
前端·后端·架构
倔强青铜33 小时前
苦练Python第18天:Python异常处理锦囊
开发语言·python
saynaihe4 小时前
ubuntu 22.04 anaconda comfyui安装
linux·运维·服务器·ubuntu
u_topian4 小时前
【个人笔记】Qt使用的一些易错问题
开发语言·笔记·qt
企鹅与蟒蛇4 小时前
Ubuntu-25.04 Wayland桌面环境安装Anaconda3之后无法启动anaconda-navigator问题解决
linux·运维·python·ubuntu·anaconda