生产者消费者模型

在实际的软件开发过程中,我们会遇到很多比较现实的场景。例如,某些模块负责去产生数据,而数据的处理则由其他模块去处理。产生数据的模块则被人形象的称为生产者,而处理数据的模块则被人形象地称为消费者。

生产者消费者模型:


为什么需要存在缓冲区?

1、降低耦合度

如果生产者与消费者分别是类,如果让生产者类直接去调用消费者类中的某个成员或方法,那么两个类之间就会存在依赖关系,那么以后消费者类的改动可能会影响生产者类,如果两者都依赖于一个缓冲区时,那么就降低了两者之间的某种联系,从而降低了两者之间的耦合度。

2、支持并发

如果生产者类调用消费者类的某个方法还会存在持续等待的问题,因为函数的调用使用的是阻塞式等待,如果同一个方法,消费者类在调用,那么生产者类想调用该方法时必须等消费者类调用完成之后方可调用。如果消费者处理数据 的速度很慢,这就会降低工作效率。因此使用生产者/消费者之后就不会存在这个问题,因为生产者消费者是两个独立的并发主体。生产者生产出数据后,将数据放进缓冲区后,然后就去生产下一个数据,不需要等待消费者去处理数据。

3、支持忙闲不均

当生产者的生产速度不稳定时,生产速度很快时,消费者没有精力去处理,那么缓冲区就将生产者生产的数据保存起来等消费者处理之后然后进行及处理。

二、队列(FIFO)缓冲区

单个生产者和一个消费者之间可以使用队列缓冲区。

当生产者与消费者是进程与线程时,使用队列缓冲区各有优缺点。

***线程***

缺点:

1、内存分配的性能

在线程模式下,生产者和消费者都各自成一个线程,生产者将头插一个数据,然后消费者在队尾读取一个数据。当队列为空时,消费者就等待,当队列满的时候,生产者就进行等待。但是存在一个问题,因为生产者和消费者进行时push或pop会进行内存分配,但系统中内存分配时,系统中有加锁/解锁机制,用户态/内核态的切换;

2、同步与互斥

同步和互斥的性能开销。在很多场合中,诸如信号量、互斥量等玩意儿的使用也是有不小的开销的(某些情况下,也可能导致用户态/核心态切换)。如果像刚才所说,生产者和消费者都很勤快,那这些开销也不容小觑啊。

基于队列的线程生产者消费者模型实现:

三、环状缓冲区

环形缓冲区所有的push和pop操作都是在一个固定的存储空间内进行。而队列缓冲区在push的时候,可能会分配存储空间用于存储新元素;在pop时,可能会释放废弃元素的存储空间。所以环形方式相比队列方式,少掉了对于缓冲区元素所用存储空间的分配、释放。这是环形缓冲区的一个主要优势。


环形缓冲区的内部实现,即可基于数组(此处的数组,泛指连续存储空间)实现。
数组在物理存储上是一维的连续线性结构,可以在初始化时,把存储空间一次性分配好,这是数组方式的优点。但是要使用数组来模拟环,就必须在逻辑上把数组的头和尾相连。在顺序遍历数组时,对尾部元
元素(最后一个数)要作一下特殊处理。访问尾部元素的下一个元素时,要重新回到头部元素(第0个元素)。

基于环状缓冲区的线程生产者消费者模型:


***进程***

跨进程的生产者/消费者模式,非常依赖于具体的进程间通讯(IPC)方式。

匿名管道:感觉管道是最像队列的IPC类型。生产者进程在管道的写端放入数据;消费者进程在管道的读端取出数据。整个的效果和线程中使用队列非常类似,区别在于使用管道就无需操心线程安全、内存分配等琐事。

优点:

1、基本上所有操作系统都支持在shell方式下使用管道符。因此很容易实现跨平台。

2、大部分编程语言都能够操作stdio,因此跨编程语言也就容易实现。

3、刚才已经提到,管道方式省却了线程安全方面的琐事。有利于降低开发、调试成本。

缺点:

1、生产者进程和消费者进程必须得在同一台主机上,无法跨机器通讯。这个缺点比较明显。

2、在一对一的情况下,这种方式挺合用。但如果要扩展到一对多或者多对一,那就有点棘手了。所以这种方式的拓展性要打个折扣。假如今后要考虑类似的扩展,这个缺点就比较明显。

3、由于管道是shell创建的,对于两边的进程不可见(程序看到的只是stdio)。在某些情况下,导致程序不便于对管道进行操纵(比如调整管道缓冲区尺寸)。

4、最后,这种方式只能单向传数据。好在大多数情况下,消费者进程不需要传数据给生产者进程。万一你确实需要信息反馈(从消费者到生产者),那就费劲了。可能得考虑换种IPC方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值