首页 > 编程语言 >详细说明Python中的Condition类(转)

详细说明Python中的Condition类(转)

时间:2023-07-18 18:11:48浏览次数:39  
标签:__ 10 Python consumed products 详细 Consumer Condition

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

相关文章

  • python使一个函数在新线程中运行的装饰器
    python在用tk编程时,界面响应函数最好在另外一个线程中运行,以免界面没有响应.为方便使用,封装了一个装饰器,调用函数时自动在另外一个线程中运行.示例代码如下:importthreadingdefrun_in_thread(func):defwrapper(*args,**kwargs):thread=threading......
  • Python3 Pandas DataFrame 对某一列求和
    在操作pandas的DataFrame的时候,常常会遇到某些列是字符串,某一些列是数值的情况,如果直接使用df_obj.apply(sum)往往会出错使用如下方式即可对其中某一列进行求和dataf_test1['diff'].sum()//diff为要求和的列......
  • python copy.copy与copy.deepcopy 区别
     importcopyorigin=[1,2,[3,4]]cop1=origin.copy()cop2=copy.deepcopy(origin)print("origin:",origin)print("cop1:",cop1)print("cop2:",cop2)origin[2][0]="hey!"print()print("origin:",......
  • Python基础(3)
    面向对象编程根据类来创建对象称为实例化。这里只过一下大概的面向对象的内容,不做细讲。可以直接查阅资料。https://www.runoob.com/python3/python3-class.html创建和使用类及实例给出一个类的使用例子:classDog:def__init__(self,name,age):self.name=na......
  • Python中的方法重写与名称修饰
    Python中的方法重写与名称修饰今天写python系统的时候,发现父类怎么老是调用不了子类重写的方法,整了好久才发现,python的名称修饰机制,好久没写代码了,这一块知识点忘干净了,下面进行总结。在Python中,方法重写是面向对象编程中的重要概念,它允许子类对父类的方法进行重新定义以满足子......
  • Python获取文件夹下文件夹的名字,并存excel为一列(方法一)
    大家好,我是皮皮。一、前言这个事情还得从前几天在Python最强王者群【东哥】问了一个Python自动化办公处理的问题,需求倒是不难,一起来看看吧。二、实现过程这里【wangning】又给了一个答案,他自己之前整理的文章,不过需要自己稍微修改下才行。后来【魏哥】看到了,并且给出了如下......
  • 如何使用python计算复杂三角函数
    当涉及到计算复杂的三角函数时,Python提供了强大的数学库和函数来帮助我们进行计算。在本篇博客中,我将介绍如何使用Python来计算复杂的三角函数。首先,我们需要导入Python的math模块,它提供了许多数学函数和常量。你可以使用以下代码导入math模块:importmath接下来,让我......
  • Python pandas.DataFrame.iat函数方法的使用
    DataFrame.iat按整数位置访问行/列对的单个值。与iloc类似,两者都提供基于整数的查找。如果只需要在DataFrame或Series中获取或设置一个值,则使用iat。Raises:当整数位置超出界限时抛出IndexError例子:>>>df=pd.DataFrame([[0,2,3],[0,4,1],[10,20,30]],.......
  • python 声波 通信 源代码
    Python声波通信简介在现代科技发展的今天,我们已经习惯了通过网络进行通信,例如使用电子邮件、即时通讯应用或者社交媒体。但是,除了这些常见的通信方式之外,还存在一种古老而有趣的通信方式,那就是声波通信。声波通信是利用声音波动传播的特性进行信息传递的一种方式。通过将信息转化......
  • python 设置系统变量
    Python设置系统变量在Python编程中,我们经常需要设置系统变量来配置程序的运行环境。系统变量是一些全局的配置参数,可以在整个操作系统中使用。Python提供了多种方式来设置系统变量,本文将介绍其中的几种常用方法,并提供相应的代码示例。方法一:使用os模块Python标准库中的os模块提......