linux:生产者消费者模型

生产者消费者模型:

这里写图片描述
如图,我们可以将这个模型理解为:中间的队列相当于一个超市里的货物,生产者是这家超市的供货商,而消费者就是去超市购物的人,即消费者。而供货商不需要关心消费者,消费者也不需要关心供货商,他们都只关心超市中有没有货物。

基于上面的描述,我们给出生产者消费者模型的概念:两个进程共享一个缓冲区,一个进程称为生产者向缓冲区中放数据,另一个称为消费者从缓冲取中取数据,当缓冲区中有数据时,生产者进程就必须可进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲取中没有数据时,消费者进程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。

为便于理解,我们用一个“321”模型:
“3”代表的是三种关系:
生产者与消费者的互斥与同步关系
生产者与生产者的互斥(或竞争)关系
消费者与消费者的互斥(或竞争)关系

“2”代表两种角色
生产者:往交易场所放东西(在计算机中一般都是数据)的人
消费者:从交易场所取东西的人

“1”代表一个交易场所
所谓交易场所就是内存中具有存储数据的一段有界缓冲区

基于链表实现生产者消费者模型:

当使用链表来模拟生产者消费者模型时,我们可以借助链表的插入来扮演生产者的角色,用链表的删除来充当消费者的角色,为了便于实现,我们直接采用链表的头插和链表的头删操作来模拟放数据和取数据这两个过程。

这里写图片描述

具体代码:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

运行结果:
这里写图片描述

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

首先,我们要清楚,在用环形队列实现生产者消费者模型时我们用到的是信号量中的PV操作,而PV操作都是原子性的。执行P操作P(S)时信号量S的值减1,若结果不为负则P(S)执行完毕,否则执行P操作的进程暂停以等待释 放。执行V操作V(S)时,S的值加1,若结果不大于0则释放一个因执行P(S)而等待的进程。对P1和P2可定义两 个信号量S1和S2,初 值分别为1和0。进程P1在向缓冲B送入数据前执行P操作P(S1),在送入数据后执行V操 作V(S2)。进程P2在从缓冲B读取数 据前先执行P操作P(S2),在读出数据 后执行V操作V(S1)。当P1往缓冲B送入一数据后信号量S1之值变为0,在该数据读出后S1之值才又变为1,因此在前一数未读出前后一数不会送入,从而保 证了P1和P2之间的同步。

我们先来了解一些关于Semaphore(信号量)的知识。
(1)初始化信号量
这里写图片描述
sem为指向信号量结构的一个指针;
pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;
value给出了信号量的初始值。

(2)释放信号量资源
这里写图片描述

(3)
这里写图片描述
函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。(P操作)
函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。

(4)
这里写图片描述
调用sem_post() 可以释放资源(V操作),使semaphore 的值加1,同时唤醒挂起等待的线程。

这里写图片描述
基于环形队列实现生产者消费者模型的规则:
(1)生产者必须快于消费者
(2)生产者不能将消费者套圈
(3)消费者不能消费时,生产者先走。
生产者满时(不能在生产时),消费者先走。

代码实现:
这里写图片描述
这里写图片描述
这里写图片描述

运行结果:
这里写图片描述

以上是单生产者单消费者模型,下面我们实现多生产者与多消费者模型。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

运行结果如下:
这里写图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值