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

Condition

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

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

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

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

while not predicate():
    con.wait()

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

notify(n=1)
默认状况下,唤醒等待此条件变量的一个线程(若是有)。调用该方法的线程必须先得到锁,不然引起RuntimeError
该方法最多唤醒n个等待中的线程,若是没有线程在等待,它就是要给无动做的操做。
注意:要被唤醒的线程实际上不会立刻从wait()方法返回(唤醒),而是等到它从新获取锁。这是由于notify()并不会释放锁,须要线程自己来释放(经过wait()或者release())orm

notify_all()
此方法相似于notify(),但唤醒的时全部等待的线程。对象

生产者与消费者 -- Condition版

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

# -*- 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()

运行结果:it

生产了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没钱了-回老家
相关文章
相关标签/搜索