[common c/c++] 为什么使用 semaphore 的生产者消费者模型需要两个信号量

正文:

信号量没有 “触及上限则阻塞post” 的原语,同时信号量除了系统限制的信号量最大值之外并没有接口可以用来设置上限。因此在一个信号量场景下,生产者在 post 信号的时候是没有束缚的,如果不控制生产量的话,会导致系统资源被耗尽。

一种方法是判断 FIFO 的尺寸,如果 FIFO 已经满了,则停止本次生产,接着sleep一定时间等待消费者从队列中取走数据,然后判断队列是否为空或者是否降到一定阈值,如果满足则继续填充队列。这种方法有一个问题,那就是如果消费者突然间在短时间内把数据都取走了,那么生产者sleep的就是影响了效率,如果缩减sleep的周期,那么又会导致cpu升高。

另外一种方法是使用两个信号量,此时不再使用一个信号量来管理整个队列的计数,而是预先把队列的上限确定下来,然后用两个信号量分别表示队列中空余(empty)位置的数量 和 已被使用(filled/full)位置的数量,这两个值的和是队列的上限。

生产者的逻辑为 :

1)wait 是否有empty位置可用(sem_wait(empty_sem)) 。

2)一旦跳出阻塞则说明有被标记为 empty 的位置可用,即有未被填充的单元,那么 lock 队列(mutex_lock/sem_wait(二元sem),这里可以选择mutex,也可以用二元sem,mutex 也同时支持 线程和进程级别。

3)填充队列。

4)unlock 队列。

5)post 增加一个 filled/full 可用位置(sem_post(filled_sem))。

消费者逻辑为:

1)wait 是否有 filled 位置可用(sem_wait(filled_sem))。

2)  一旦跳出阻塞则说明有标记为的 filled 的位置可用,即有已经被填充的单元,那么 lock 队列(mutex_lock/sem_wait(二元sem),这里可以选择mutex,也可以用二元sem,mutex 也同时支持 线程和进程级别。

3)从队列中取数据。

4)unlock 队列

5)post 增加一个 empty 可用位置(sem_post(empty_sem))。
 

伪代码:

mutex
semFull = 0 // Initially, all slots are empty. Thus full slots are 0 
semEmpty = n // All slots are empty initially 
 
 
 
//Solution for Producer – 
 
do{
 
//produce an item
 
wait(semEmpty);      //semEmpty - 1
wait(mutex);         //mutex.lock
 
//place in buffer
 
signal(mutex);       //mutex.unlock
signal(semFull );    //semFull + 1
 
}while(true)
 
 
 
//Solution for Consumer – 
 
do{
 
wait(full);           //semFull - 1
wait(mutex);          //mutex.lock
 
// consume item from buffer
 
signal(mutex);        //mutex.unlock
signal(empty);        //semEmpty + 1
 
 
}while(true)

参考:

Producer Consumer Problem using Semaphores | Set 1 - GeeksforGeeksA Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.icon-default.png?t=N7T8https://www.geeksforgeeks.org/producer-consumer-problem-using-semaphores-set-1/?ref=lbp

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值