add by zhj: 之前只知道在Queue的实现中使用了Condition对象,可以实现生产者消费者功能,但具体怎么使用Condition还是一知半解,看了这篇文章,终于懂了。很多事情往往一时看不明白,看得多了,某一天就突然明白了。
原文:https://blog.csdn.net/ckk727/article/details/99950843
作者:二十七º
网站:CSDN 互斥锁Lock和RLock只能提供简单的加锁和释放锁等功能,它们的主要作用是在多线程访问共享数据时,保护共享数据,防止数据被脏读脏写,保证数据和关键代码的完整性。在此基础上,Python提供了Condition类,Condition类不仅自身依赖于Lock和RLock,即具有它们的阻塞特性,此外还提供了一些有利于线程通信,以及解决复杂线程同步问题的方法,它也被称作条件变量。一、Condition类提供的方法
1. 构造方法:__init__(self,lock=None)
1)从Condition类的构造方法可以看出,Condition类总是与一个锁相关联。在创建一个Condition类的同时就应该传入Condition类需要绑定的Lock对象;
2)另外,如果不指定lock参数,那么Python会自动创建一个与之绑定的Lock对象。
2. acquire方法
acquire(timeout)
调用Condition类关联的Lock/RLock的acquire()方法。
3. release方法
release()
调用Condition类关联的Lock/RLock的release()方法。
4. wait方法
wait(timeout)
1)线程挂起,直到收到一个notify通知或者等待时间超出timeout才会被唤醒;
2)注意:wait()必须在已获得Lock的前提下调用,否则会引起RuntimeError错误。
5. notify方法
notify(n=1)
1)唤醒在Condition的waiting池中的n(参数n可设置,默认为1)个正在等待的线程并通知它,受到通知的线程将自动调用acquire()方法尝试加锁;
2)如果waiting池中有多个线程,随机选择n个唤醒;
3)必须在已获得Lock的前提下调用,否则将引发错误。
6. notify_all方法notify_all()
唤醒waiting池中的等待的所有线程并通知它们。
二、实例详解
生产者消费者问题
问题:
假设有一群生产者(Producer)和一群消费者(Consumer)通过一个市场来交互产品。生产者的”策略“是如果市场上剩余的产品少于500个,那么就生产50个产品放到市场上;而消费者的”策略“是如果市场上剩余产品的数量多于100个,那么就消费10个产品。
代码:
import threading from time import sleep #商品 product = 500 #条件变量 con = threading.Condition(threading.Lock()) #生产者类 #继承Thread类 class Producer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果获得了锁 if con.acquire(): #处理产品大于等于500和小于500的情况 if product >= 500: #如果大于等于500,Producer不需要额外操作,于是挂起 con.wait() else: product += 50 message = self.name + " produced 50 products." print(message) #处理完成,发出通知告诉Consumer con.notify() #释放锁 con.release() sleep(1) #消费者类 #继承Thread类 class Consumer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果获得了锁 if con.acquire(): #处理product小于等于100和大于100的两种情况 if product <= 100: #如果小于等于100,Consumer不需要额外操作,于是挂起 con.wait() else: product -= 10 message = self.name + " consumed 10 products." print(message) #处理完成,发出通知告诉Producer con.notify() #释放锁 con.release() sleep(1) def main(): #创建两个Producer for i in range(2): p = Producer('Producer-%d'%i) p.start() #创建三个Consumer for i in range(3): c = Consumer('Consumer-%d'%i) c.start() if __name__ == '__main__': main()
运行结果:
Consumer-0 consumed 10 products. Consumer-1 consumed 10 products. Consumer-2 consumed 10 products. Producer-0 produced 50 products. Consumer-0 consumed 10 products. Consumer-1 consumed 10 products. Consumer-2 consumed 10 products. Producer-0 produced 50 products. Consumer-1 consumed 10 products. Consumer-0 consumed 10 products. Consumer-2 consumed 10 products. Consumer-1 consumed 10 products. ......
互斥锁Lock和RLock只能提供简单的加锁和释放锁等功能,它们的主要作用是在多线程访问共享数据时,保护共享数据,防止数据被脏读脏写,保证数据和关键代码的完整性。在此基础上,Python提供了Condition类,Condition类不仅自身依赖于Lock和RLock,即具有它们的阻塞特性,此外还提供了一些有利于线程通信,以及解决复杂线程同步问题的方法,它也被称作条件变量。
一、Condition类提供的方法构造方法:
__init__(self,lock=None)11)从Condition类的构造方法可以看出,Condition类总是与一个锁相关联。在创建一个Condition类的同时就应该传入Condition类需要绑定的Lock对象;
2)另外,如果不指定lock参数,那么Python会自动创建一个与之绑定的Lock对象。
acquire(timeout)1调用Condition类关联的Lock/RLock的acquire()方法。
release()1调用Condition类关联的Lock/RLock的release()方法。
wait(timeout)11)线程挂起,直到收到一个notify通知或者等待时间超出timeout才会被唤醒;
2)注意:wait()必须在已获得Lock的前提下调用,否则会引起RuntimeError错误。
notify(n=1)11)唤醒在Condition的waiting池中的n(参数n可设置,默认为1)个正在等待的线程并通知它,受到通知的线程将自动调用acquire()方法尝试加锁;
2)如果waiting池中有多个线程,随机选择n个唤醒;
3)必须在已获得Lock的前提下调用,否则将引发错误。
notify_all()1唤醒waiting池中的等待的所有线程并通知它们。
二、实例详解生产者消费者问题
问题:
假设有一群生产者(Producer)和一群消费者(Consumer)通过一个市场来交互产品。生产者的”策略“是如果市场上剩余的产品少于500个,那么就生产50个产品放到市场上;而消费者的”策略“是如果市场上剩余产品的数量多于100个,那么就消费10个产品。
代码:
import threadingfrom time import sleep
#商品product = 500#条件变量con = threading.Condition(threading.Lock())
#生产者类#继承Thread类class Producer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果获得了锁 if con.acquire(): #处理产品大于等于500和小于500的情况 if product >= 500: #如果大于等于500,Producer不需要额外操作,于是挂起 con.wait() else: product += 50 message = self.name + " produced 50 products." print(message) #处理完成,发出通知告诉Consumer con.notify() #释放锁 con.release() sleep(1)#消费者类#继承Thread类class Consumer(threading.Thread): def __init__(self,name): super().__init__() self.name = name def run(self): global product while True: #如果获得了锁 if con.acquire(): #处理product小于等于100和大于100的两种情况 if product <= 100: #如果小于等于100,Consumer不需要额外操作,于是挂起 con.wait() else: product -= 10 message = self.name + " consumed 10 products." print(message) #处理完成,发出通知告诉Producer con.notify() #释放锁 con.release() sleep(1) def main(): #创建两个Producer for i in range(2): p = Producer('Producer-%d'%i) p.start() #创建三个Consumer for i in range(3): c = Consumer('Consumer-%d'%i) c.start()
if __name__ == '__main__': main()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869运行结果:
Consumer-0 consumed 10 products.Consumer-1 consumed 10 products.Consumer-2 consumed 10 products.Producer-0 produced 50 products.Consumer-0 consumed 10 products.Consumer-1 consumed 10 products.Consumer-2 consumed 10 products.Producer-0 produced 50 products.Consumer-1 consumed 10 products.Consumer-0 consumed 10 products.Consumer-2 consumed 10 products.Consumer-1 consumed 10 products.......————————————————版权声明:本文为CSDN博主「二十七º」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/ckk727/article/details/99950843 标签:__,10,Python,consumed,products,详细,Consumer,Condition From: https://www.cnblogs.com/ajianbeyourself/p/17563792.html