进程同步之生产者消费者模型

一、概念引入
进程同步之生产者消费者模型_第1张图片
例如寄信
我(生产者) 邮递员(消费者)

我把信件写好 -----相当于生产者生产数据
我把信放到邮筒-----相当于把生产者的数据放入到缓冲区
邮递员把信从邮筒取出-----相当于消费者把数据从缓冲区取出
邮递员把信拿去邮局处理------相当于消费者处理数据

二、为什么要使用生产者-消费者模型

生产者消费者模型通过一个容器解决生产者和消费者的强耦合(强度相互依赖)问题。生产者消费者彼此间不直接通讯,而通过阻塞队列进行通讯,即生产者生产完数据,不用等待消费者消费数据,直接扔给阻塞队列,消费者不找生产者要数据,而是从阻塞队列里取,阻塞队列相当于一个缓冲区,平衡生产者和消费者的处理能力。这个阻塞队列就是用给生产者和消费者解耦的。

三、生产者-消费者模型的优点

1 解耦:降低生产者和消费之间的依赖关系

例如上述写信的例子
如果不使用邮筒(缓冲区)需要把信件交给邮递员,但是前提是你得认识快递员(相当于生产者消费者的强耦合),万一邮递员换人了你还得重新认识一下(相当于消费者变化导致修改生产者代码)。而对邮筒来说比较固定,你依赖它的成本比较低(相当于和缓冲区之间的弱耦合)。

2 支持并发

即生产者和消费者是两个可以独立的并发主体,互不干扰的运行
从寄信的例子看,如果没有邮筒就需要在路口等待邮递员过来收(相当于生产者阻塞);又或者邮递员挨家挨户的询问谁要寄信(相当于消费者轮询)。不管是那种方法效率都比较低下。

3 支持忙闲不均

如果生产数据的速度时快时慢,缓冲区可以对其进行适当缓冲。当生产的数据太块时,消费者来不及处理,未处理的数据可以暂时存在缓冲区。等生产者的生产速度慢下来,消费者再慢慢处理掉。
例如寄信的例子,假设邮递员一次只能带1000封信,万一某次碰到了中秋节送贺卡,需要邮递的信封数量超过1000封,这个时候邮筒(缓冲区)就派上用场了,邮递员吧来不及带走的信封暂存在邮筒中,等下次再过来拿。

四、生产者-消费者模型记忆规则

三二一原则:三种关系,两个角色,一个场所

三种关系:
1生产者-生产者(互斥)
2生产者-消费者(同步与互斥)
3消费者-消费者(互斥)

两个角色:
1生产者
2消费者

一个场所:
缓冲区

五、生产者-消费者模型学习

1 、确定数据单元
简单说就是 ,每次生产者放到缓冲区,就是一个数据单元;每次消费者从缓冲区拿走,也是一个数据单元

数据单元的特性:
1关联到业务对象:数据单元必须关联到某种业务对象
2完整性:保证每一个数据单元的完整
3独立性:各个数据单元之间没有互相依赖

2、学习队列缓冲区

线程方式

内存分配的开销问题---》环形缓冲区
同步和互斥的性能 ----》双缓冲区
适用队列的场合  -----》数据流量不是很大

进程方式

1 匿名管道:生产者进程再管道的写端放入数据;消费者进程在管道的读端取出数据
好处:
    跨平台方便,跨语言方便。
    有利于降低开发成本,调试成本。
不足:
    生产者进程和消费者进程必须在同一台主机上
    只适用于一对一通信
    某些情况下,程序不便对管道进行操作(比如调整管道缓冲区尺寸)
    只能单向通信
2 socket(TCP方式):
    类似IPC方式,同样保证了数据顺序到达,同样有缓冲机制
优点:
    1可以跨机器(便于实现分布式)
    2便于将来扩展称为一对多或多对一
    3可以设置阻塞和非阻塞方法,使用灵活
    4支持双向通讯,有利于消费者反馈信息
不足:
    编程复杂
    虽然TCP很多时候比UDP可靠,但鉴于跨机器通讯的不可预料性,
    可以在生产者进程和消费者进程内部各自引入基于线程的“生产者-消费者模式”

进程同步之生产者消费者模型_第2张图片

你可能感兴趣的:(Linux)