Linux - POSIX信号量,基于环形队列的生产者消费者模型

本文介绍了Linux下POSIX信号量作为线程同步机制,探讨了如何使用信号量实现生产者消费者模型。通过将共享资源划分为小资源并利用信号量进行保护,实现了并发访问。文章详细讲解了二进制和计数信号量,并给出了基于环形队列的生产消费者模型,解释了如何结合信号量解决环形队列的判空判满问题,以及如何处理多生产者多消费者的情况。
摘要由CSDN通过智能技术生成

信号量

在Linux下,POSIX信号量是一种线程同步机制,用于控制多个线程之间的访问顺序。POSIX信号量可以用于实现线程之间的互斥或者同步。


在之前的阻塞队列生产者消费者模型中,阻塞队列是一个共享资源,不管是生产者还是消费者,任何时刻只允许一个线程访问共享资源,所以对阻塞队列进行了加锁保护,使阻塞队列成为为临界资源。在这里,是将整个共享资源(阻塞队列)当作一个整体使用的。

信号量使用思路:一个共享资源,不当作整体使用,将其划分为若干个小的共享资源,使得不同的执行流访问不同的小共享资源,本质上,当不同执行流访问不同的小共享资源时,不需要进行加锁保护,可以并发执行。而如果两个执行流访问到了同一个小的共享资源时,再进行互斥保护共享资源。


POSIX信号量提供了两种类型的信号量:二进制信号量和计数信号量。二进制信号量只有两个取值:0和1,它用于表示资源是否被占用。计数信号量可以有多个取值,它表示可用资源的数量。

二进制信号量可以充当互斥锁的作用。因为信号量的初始值为1,p相当于加锁,v相当于解锁。

计数信号量的值通常被称为“资源计数器”,它记录了当前可用的共享资源数量。当一个线程需要使用共享资源时,它会尝试获取计数信号量,如果当前可用资源数量大于0,则线程可以获取资源并将计数信号量的值减1。如果当前可用资源数量为0,则表示共享资源已被占用,线程需要等待直到有资源可用。

POSIX信号量接口

       int sem_init(sem_t *sem, int pshared, unsigned int value); // 初始化
       int sem_destroy(sem_t *sem);    // 销毁
       int sem_wait(sem_t *sem);       // 申请信号量,P操作
       int sem_post(sem_t *sem);       // 释放信号量,V操作

因为信号量本质就是一个计数器,记录着当前的资源数目,其中初始化时的value值就表示初始时的资源数目。

在使用POSIX信号量时,线程可以通过调用sem_wait()函数来请求获取信号量,如果当前信号量的值大于0,则线程可以继续执行,同时信号量的值会减1;否则线程将被阻塞,等待信号量的值变为大于0。当线程释放资源时,可以通过调用sem_post()函数来释放信号量,使得其它线程可以获取资源。

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

1.缓冲区的改变

基于环形队列的生产者消费者模型,对比之前的基于阻塞队列的生产者消费者模型,只是缓冲区的具体数据结构变了。两个角色:生产者,消费者。三种关系:生产者与生产者:互斥。消费者与消费者:互斥。生产者与消费者:互斥与同步。

如上图,环节队列是逻辑抽象结构,底层的物理结构是数组。要想达到环形队列的效果,只需在访问数组的最后一个元素的下一个元素时将下标 %= size即可。再者,环形队列有一个判空和判满的问题,因为这里的容量是有上限的,从数据结构的角度来说,一般会有一个start和end下标,当start == end时为空,而当数据为满时,不能也将start == end标定为满,因为这样空和满的判断条件就相同了。解决方法࿱

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值