python 多线程笔记(5)-- 生产者/消费者模式

 

我们已经知道,对公共资源进行互斥访问,可以使用Lock上锁,或者使用RLock去重入锁。

 

但是这些都只是方便于处理简单的同步现象,我们甚至还不能很合理的去解决使用Lock锁带来的死锁问题。

要解决更复杂的同步问题,就必须考虑别的办法了。

 

threading提供的Condition对象提供了对复杂线程同步问题的支持。

Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify方法。

 

使用Condition的主要方式为:

线程首先acquire一个条件变量,然后判断一些条件。如果条件不满足则wait;如果条件满足,进行一些 处理改变条件后,通过notify方法通知其他线程,其他处于wait状态的线程接到通知后会重新判断条件。不断的重复这一过程,从而解决复杂的同步问 题。

 

下面我们通过很著名的“生产者-消费者”模型来来演示下,在Python中使用Condition实现复杂同步。

 

生产者和消费者,各一个线程,双方将会围绕products来产生同步问题,首先是2个生成者生产products ,而接下来的10个消费者将会消耗products

import threading
import time

condition = threading.Condition()
products = 0

class Producer(threading.Thread):
    '''生产者'''
    ix = [0] # 生产者实例个数
             # 闭包,必须是数组,不能直接 ix = 0
    def __init__(self, ix=0):
        super().__init__()
        self.ix[0] += 1
        self.setName('生产者' + str(self.ix[0]))

    def run(self):
        global condition, products

        while True:
            if condition.acquire():
                if products < 10:
                    products += 1;
                    print("{}:库存不足(10-)。我努力生产了1件产品,现在产品总数量 {}".format(self.getName(), products))
                    condition.notify()
                else:
                    print("{}:库存充足(10+)。让我休息会儿,现在产品总数量 {}".format(self.getName(), products))
                    condition.wait();
                condition.release()
                time.sleep(2)

class Consumer(threading.Thread):
    '''消费者'''
    ix = [0] # 消费者实例个数
             # 闭包,必须是数组,不能直接 ix = 0
    def __init__(self):
        super().__init__()
        self.ix[0] += 1
        self.setName('消费者' + str(self.ix[0]))

    def run(self):
        global condition, products

        while True:
            if condition.acquire():
                if products > 1:
                    products -= 1
                    print("{}:我消费了1件产品,现在产品数量 {}".format(self.getName(), products))
                    condition.notify()
                else:
                    print("{}:只剩下1件产品,我停止消费。现在产品数量 {}".format(self.getName(), products))
                    condition.wait();
                condition.release()
                time.sleep(2)

if __name__ == "__main__":
    for i in range(2):
        p = Producer()
        p.start()

    for i in range(10):
        c = Consumer()
        c.start()

 

另外:

Condition对象的构造函数可以接受一个Lock/RLock对象作为参数,

如果没有指定,则Condition对象会在内部自行创建一个 RLock;

除了notify方法外,Condition对象还提供了notifyAll方法,可以通知waiting池中的所有线程尝试acquire 内部锁。

由于上述机制,处于waiting状态的线程只能通过notify方法唤醒,所以notifyAll的作用在于防止有线程永远处于沉默状态。

 

时间: 2024-08-01 04:15:59

python 多线程笔记(5)-- 生产者/消费者模式的相关文章

python 多线程笔记(6)-- 生产者/消费者模式(续)

  用 threading.Event() 也可以实现生产者/消费者模式 (自己拍脑袋想出来的,无法知道其正确性,请大神告知为谢!)   import threading import time import random products = 20 class Producer(threading.Thread): '''生产者''' ix = [0] # 生产者实例个数 # 闭包,必须是数组,不能直接 ix = 0 def __init__(self): super().__init__()

用Python多线程实现生产者消费者模式

什么是生产者消费者模式 在软件开发的过程中,经常碰到这样的场景: 某些模块负责生产数据,这些数据由其他模块来负责处理(此处的模块可能是:函数.线程.进程等).产生数据的模块称为生产者,而处理数据的模块称为消费者.在生产者与消费者之间的缓冲区称之为仓库.生产者负责往仓库运输商品,而消费者负责从仓库里取出商品,这就构成了生产者消费者模式. 结构图如下: 为了大家容易理解,我们举一个寄信的例子.假设你要寄一封信,大致过程如下: 你把信写好--相当于生产者生产数据 你把信放入邮箱--相当于生产者把数据放

聊聊并发:生产者消费者模式

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这个问题于是引入了生产者和消费者模式. 什么是生产者消费者模式 生产者

聊聊并发(十)生产者消费者模式

本文首发于InfoQ   作者:方腾飞  校对:张龙 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程.在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据.同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者.为了解决这种生产消费能力

Qt之线程同步(生产者消费者模式 - QWaitCondition)

简述 生产者将数据写入缓冲区,直到它到达缓冲区的末尾,这时,它从开始位置重新启动,覆盖现有数据.消费者线程读取数据并将其写入标准错误. Wait condition(等待条件)比单独使用 mutex(互斥量)有一个更高级的并发性,如果缓冲区的访问由一个 QMutex 把守,当生产者线程访问缓冲区时,消费者线程将无法访问.然而,两个线程同时访问不同的缓冲区是没有害处的. 示例包含两个类:Producer 和 Consumer,均继承自 QThread.循环缓冲区用于两个类之间的沟通,同步工具用于保

Qt之线程同步(生产者消费者模式 - QSemaphore)

简述 生产者将数据写入缓冲区,直到它到达缓冲区的末尾,此时,它将从开始位置重新启动,覆盖现有数据.消费者线程读取数据并将其写入标准错误. Semaphore(信号量) 比 mutex(互斥量)有一个更高级的并发性.如果缓冲区的访问由一个 QMutex 把守,当生产者线程访问缓冲区时,消费者线程将无法访问.然而,有两个线程同一时间访问不同的缓冲区是没有害处的. 示例包括两个类:Producer 和 Consumer,均继承自 QThread.循环缓冲区用于这两个类之间的沟通,信号量用于保护全局变量

leizi求指教-生产者消费者模式在什么情况下用到?

问题描述 生产者消费者模式在什么情况下用到? 生产者消费者通常都用来解决哪类问题?什么情况下需要想到用到生产者消费者模式呢? 解决方案 一般就是任务队列的时候,比如你有专门处理的任务的线程,同时有生成任务的线程,这样为了好控制,一般是把任务通过队列的方式来传递这样可以有多个线程做生产者,它们只需要把任务不停的丢入队列,同样很多线程做消费者,它们不停的从队列中取任务执行

生产者消费者模式浅析

        原文地址:http://blog.csdn.net/lenyusun/article/details/6609786         由于最近工作中,涉及到生产者消费者设计模式,对此有一些体会,所以总结一下,与大家分享.         什么是生产者消费者模式?         在工作中,大家可能会碰到这样一种情况:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类.函数.线程.进程等).产生数据的模块,就形象地称为生产者:而处理数据的模块,就称为

Lock、Condition实现简单的生产者消费者模式示例_java

复制代码 代码如下: package condition; import java.util.ArrayList;import java.util.List;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock; /** * 利用Lock.Condition实现生产者消费者模式 * @aut