[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 = 1
Full = 0 // Initially, all slots are empty. Thus full slots are 0
Empty = n // All slots are empty initially
//Solution for Producer –
do{
//produce an item
wait(empty);
wait(mutex);
//place in buffer
signal(mutex);
signal(full);
}while(true)
//Solution for Consumer –
do{
wait(full);
wait(mutex);
// consume item from buffer
signal(mutex);
signal(empty);
}while(true)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!