美文网首页
python多线程--Condition(条件对象)

python多线程--Condition(条件对象)

作者: 雷子_ | 来源:发表于2018-10-23 20:05 被阅读0次

    Condition

    class threading.Condition(lock=None
    这个类实现条件变量对象。条件变量允许一个或多个线程等待,知道它们被另一个线程唤醒。
    如果给出了lock参数而不是None,则它必须是LcokRLock对象,并以它作为底层的锁。否则将默认创建一个RLock对象。
    Condition遵循上下文管理协议。
    方法:
    acquire(*args)
    获取锁。这个方法调用底层锁的相应方法。

    release()
    释放锁。这个方法调用底层锁的相应方法。

    wait(timeout=None)
    线程挂起,等待被唤醒(其他线程的notify方法)或者发生超时。调用该方法的线程必须先获得锁,否则引发RuntimeError
    该方法会释放底层锁,然后阻塞,直到它被另一个线程中的相同条件变量的notify()notify_all()方法唤醒,或者发生超时。一旦被唤醒或超时,它会重新获取锁并返回。
    返回值为True,如果给定timeout并发生超时,则返回False

    wait_for(predicate, timeout=None)
    等待知道条件变量的返回值为Truepredicate应该是一个返回值可以解释为布尔值的可调用对象。可以设置timeout以给定最大等待时间。
    该方法可以重复调用wait(),直到predicate的返回值解释为True,或发生超时。该方法的返回值就是predicate的最后一个返回值,如果发生超时,返回值为False
    如果忽略超时功能,该方法大致相当于:

    while not predicate():
        con.wait()
    

    它与wait()的规则相同:调用前必须先获取锁,阻塞时释放锁,并在被唤醒时重新获取锁并返回。

    notify(n=1)
    默认情况下,唤醒等待此条件变量的一个线程(如果有)。调用该方法的线程必须先获得锁,否则引发RuntimeError
    该方法最多唤醒n个等待中的线程,如果没有线程在等待,它就是要给无动作的操作。
    注意:要被唤醒的线程实际上不会马上从wait()方法返回(唤醒),而是等到它重新获取锁。这是因为notify()并不会释放锁,需要线程本身来释放(通过wait()或者release())

    notify_all()
    此方法类似于notify(),但唤醒的时所有等待的线程。

    生产者与消费者 -- Condition版

    场景:生产者一次性生产5个商品(生产过程中不可购买),之后通知消费者抢购,当商品卖完后,由消费者通知生产者开始生产。

    # -*- coding:utf-8 -*-
    import threading
    import time
    
    
    num = 0
    con = threading.Condition()
    
    
    class Producer(threading.Thread):
        """生产者"""
        def run(self):
            global num
            # 获取锁
            con.acquire()
            while True:
                num += 1
                print('生产了1个,现在有{0}个'.format(num))
                time.sleep(1)
                if num >= 5:
                    print('已达到5个,不再生产')
                    # 唤醒消费者
                    con.notify()
                    # 等待-释放锁;被唤醒-获取锁
                    con.wait()
            # 释放锁
            con.release()
    
    
    class Customer(threading.Thread):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.money = 7
    
        def run(self):
            global num
            while self.money > 0:
                # 由于场景是多个消费者进行抢购,如果将获取锁操作放在循环外(如生产者),
                # 那么一个消费者线程被唤醒时会锁住整个循环,无法实现另一个消费者的抢购。
                # 在循环中添加一套"获取锁-释放锁",一个消费者购买完成后释放锁,其他消费者
                # 就可以获取锁来参与购买。
                con.acquire()
                if num <= 0:
                    print('没货了,{0}通知生产者'.format(
                        threading.current_thread().name))
                    con.notify()
                    con.wait()
                self.money -= 1
                num -= 1
                print('{0}消费了1个, 剩余{1}个'.format(
                    threading.current_thread().name, num))
                con.release()
                time.sleep(1)
            print('{0}没钱了-回老家'.format(threading.current_thread().name))
    
    
    if __name__ == '__main__':
        p = Producer(daemon=True)
        c1 = Customer(name='Customer-1')
        c2 = Customer(name='Customer-2')
        p.start()
        c1.start()
        c2.start()
        c1.join()
        c2.join()
    

    运行结果:

    生产了1个,现在有1个
    生产了1个,现在有2个
    生产了1个,现在有3个
    生产了1个,现在有4个
    生产了1个,现在有5个
    已达到5个,不再生产
    Customer-1消费了1个, 剩余4个
    Customer-2消费了1个, 剩余3个
    Customer-1消费了1个, 剩余2个
    Customer-2消费了1个, 剩余1个
    Customer-1消费了1个, 剩余0个
    没货了,Customer-2通知生产者
    生产了1个,现在有1个
    生产了1个,现在有2个
    生产了1个,现在有3个
    生产了1个,现在有4个
    生产了1个,现在有5个
    已达到5个,不再生产
    Customer-1消费了1个, 剩余4个
    Customer-2消费了1个, 剩余3个
    Customer-1消费了1个, 剩余2个
    Customer-2消费了1个, 剩余1个
    Customer-1消费了1个, 剩余0个
    没货了,Customer-2通知生产者
    生产了1个,现在有1个
    生产了1个,现在有2个
    生产了1个,现在有3个
    生产了1个,现在有4个
    生产了1个,现在有5个
    已达到5个,不再生产
    Customer-1消费了1个, 剩余4个
    Customer-2消费了1个, 剩余3个
    Customer-2消费了1个, 剩余2个
    Customer-1消费了1个, 剩余1个
    Customer-1没钱了-回老家
    Customer-2消费了1个, 剩余0个
    没货了,Customer-2通知生产者
    生产了1个,现在有1个
    生产了1个,现在有2个
    生产了1个,现在有3个
    生产了1个,现在有4个
    生产了1个,现在有5个
    已达到5个,不再生产
    Customer-2消费了1个, 剩余4个
    Customer-2没钱了-回老家
    

    相关文章

      网友评论

          本文标题:python多线程--Condition(条件对象)

          本文链接:https://www.haomeiwen.com/subject/mbxzzftx.html