Linux线程信号量

信号量基本性质

信号量的本质实际上就是一把计数器,可以用来描述临界资源中资源数目的大小,即最多能有多少资源可以分配给线程。
临界资源可以被划分为一个一个的小资源,如果处理得当,有可能让多个线程同时访问临界资源的不同区域,从而实现并发。每个线程想访问临界资源,都需要先申请信号量资源,使用这个计数器可以实现对临界资源的预定机制。

信号量的基本操作函数

信号量初始化

在这里插入图片描述
信号量也是一种特殊的数据类型—sem_t,信号量需要对其进行初始化操作,上图是对信号量进行初始化的函数,使用该参数需要控制的只有第一个和第三个参数
即第一个参数传入需要进行初始化的信号量
第二个参数pshared中0表示线程间共享,非零表示进程间共享,这里设置为0即可
第三个参数表示信号量初始值,上面说过信号量实际上是一把计数器,这里是设置计数器的大小。

信号量的销毁

在这里插入图片描述
信号量不仅需要手动进行初始化申请,而且在使用完成后还需要对其进行手动销毁释放。上图是信号量的销毁函数,这里只需要传入所需要销毁的信号量即可。

信号量相关操作

信号量对应的相关操作函数一般只有两种:即P操作和V操作
这里P操作是进行申请信号量,对应计数器的–操作
V操作是进行释放信号量操作,对应计数器的++操作
下面分别来介绍信号的P操作和V操作相对应的操作函数。

sem_wait

在这里插入图片描述
上图中sem_wait是等待信号量,会将信号量的值减1,相当于是P操作,该函数也比较简单,直接传入需要操作的信号量即可

sem_post

在这里插入图片描述
上图所示的操作是释放信号量的函数接口,即V操作,表示资源使用完毕,可以归还资源,即会将信号量的值加1,这里也只需要传入需要进行操作的信号量即可
下面来使用信号量操作一个环形队列来实现一个生产者消费者模型,来实际使用一下信号量。

使用信号量实现生产者消费者模型

环形队列基本原理

环形队列有多种实现方式,他既可以使用数组来实现环形队列,也可以使用链表来实现环形队列。这里主要介绍使用数组来实现环形队列的方式。
用数组来实现环形队列,需要先设置数组的大小。其次需要镂空一个位置,从而能够方便判空判满。
环形队列数组需要使用两个数组下标来进行控制,一个是代表拿的位置即队列的头,另一个代表放数据的位置即队列的尾。如果这两个下标指向同一个位置,则此时代表队列为空,如果放的位置下标+1刚好等于拿的位置下标,则此时队列为满,不能再进行放数据操作了。

生产者消费者模型基本思想

生产者和消费者在开始的时候指向的是同一个位置,在队列为满的时候生产者和消费者也是指向同一个位置。
队列为空或者为满的时候不能让生产者和消费者同时进行,即此时两者为互斥和同步关系,因为队列为空的时候消费者就不能再进行消费了,而队列为满的时候生产者也不能再进行生产了,所以为空的时候要让生产者执行,为满的时候要让消费者执行。
当队列不为空也不为满的情况下,生产者和消费者指向的一定不是同一个位置,这种情况下生产和消费可以同时并发执行。
生产者需要关心的是环形队列中空的位置
消费者需要关系的是环形队列中的数据
生产者和消费者需要满足以下规则:
规则1:生产者不能把消费者套一个圈(领先一圈)
规则2:消费者不能超过生产者
规则3:当指向同一个位置的时候,要根据空、满状态,来判断让谁先执行
其他:除此以外,生产者和消费者可以并发执行

基本实现代码

下面是环形队列的基本实现代码,这里是使用一个模板类进行实现,队列中可以存放各种类型的数据,基本数据类型这里使用的是stl中的vector容器来实现数组结构。需要设置相关的数组大小以及信号量大小。信号量需要设置两个,一个是代表数组中空位置资源,另一个代表数组中的数据个数。另外为了针对多生产者和多消费者的情况,这里还需要申请两把锁分别给生产者和消费者。最后设置两个变量即c_step_和p_step_作为下标来判断此时环形队列中的情况。
信号量和锁的申请释放在环形队列中的构造和析构函数中完成即可
环形队列中最关键的就是下面的Push和Pop接口函数,这两个函数一个是出数据一个是放数据,分别对应的是生产者和消费者。
其中Push的实现主要需要注意的是每放进去一个数据,需要对空位置进行P操作,并对数据信号量进行V操作,然后将数据放入数组中,再对p_step_进行++操作,为了防止下标越界,可以对下标进行取模操作
Pop操作的实现主要需要注意的是每拿出一个数据,需要对空位置进行V操作,并对数据位置进行P操作,并用输出型参数接收取出的值。最后对c_step_进行++操作,为了防止下标越界,需要对下标进行取模操作。

#include<iostream>
#include<vector>
#include<semaphore.h>
#include<pthread.h>
namespace ns_ring_queue
{
   
    const int g_cap_default = 10;
    template<class T>
    class RingQueue
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值