3.9 生产者/消费者模式
生产者/消费者模式是五个同步问题的经典模型之一,从字面意义上理解,某个模块负责生产数据,而另一个模块负责处理这些数据,那么产生数据的模块,就称为生产者;而消费数据的模块就称为消费者。但是生产者/消费者模式还有一个重要的地方就是缓存区,你可以把它理解为一个古时候的媒婆,也就是现在的红娘,生产者把产生的数据放入缓存区,消费者从缓存区取得数据进行处理。
1. 生产者/消费者模式的优点
解耦
生产者与消费者之间没有直接依赖,都依赖于缓存区。
并发
正因为生产者与消费者没有直接耦合在一起,所以生产者与消费者是两个独立的并发主体,生产者把数据生产出来,放到缓存区,即可继续生产数据,消费者亦是如此。
支持任务不均
有了缓冲区以后,如果数据产生与处理的速度不同,消费者未能及时处理的数据可以暂时存放在缓冲区。等生产者的制造速度放慢下拉,消费者再进行消化。
2. 生产者/消费者模型的原则
生产者与生产者之间是互斥关系。
生产者消费者之间是同步与互斥关系。
消费者与消费者之间是互斥关系。
3. 代码示例
我们知道,进程之间理论上是不可以直接通信和传递数据的。为了消除这个限制,我们可以借助一些第三方通道,比如消息队列。当然 multiprocessing 模块已经包装了底层机制,提供了 Queue、Pipes 等多种方式来交换数据,所以我们用Queue来演示,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据,一个简单的生产者消费者模型:
import time
import random
from multiprocessing import Process, Queue
def PUT(q):
for value in range(1,5+1):
print('存放 %d 到队列里.' % value)
q.put(value)
time.sleep(random.random())
def GET(q):
while True:
value = q.get(True)
print('从队列之中取出了 %d.' % value)
if __name__ == '__main__':
q = Queue()
pw = Process(target=PUT, args=(q,))
pr = Process(target=GET, args=(q,))
pw.start()
pr.start()
pw.join()
print('kill GET')
pr.terminate()
运行结果如下:
存放 1 到队列里.
从队列之中取出了 1.
存放 2 到队列里.
从队列之中取出了 2.
存放 3 到队列里.
从队列之中取出了 3.
存放 4 到队列里.
从队列之中取出了 4.
存放 5 到队列里.
从队列之中取出了 5.
kill GET
这样,我们就完成了一个简单的生产者/消费者模型示例。