Python 中高级知识 threading Condition

Condition

条件变量总是与某种类型的锁对象相关联,锁对象可以通过传入获得,或者在缺省的情况下自动创建。当多个条件变量需要共享同一个锁时,传入一个锁很有用。

条件变量算是python变量里面非常全能的工具,传入的Lock是什么,你可以产生特定的线程同步条件,满足你的同步场景。

官方文档:https://docs.python.org/zh-cn/3.7/library/threading.html#condition-objects

使用

最简单的消费-生产模型

# !/usr/bin/env python3
# -*- coding: utf-8 -*
from threading import Condition, Thread
 
con = Condition()
 
 
def producer(condition: Condition):
    while True:
        condition.acquire()
        print("股票跌了,买入")
        condition.notify()
        condition.wait()
        condition.release()
 
 
def consumer(condition: Condition):
    while True:
        condition.acquire()
        print("股票涨了,卖出")
        condition.notify()
        condition.wait()
        condition.release()
 
 
if __name__ == "__main__":
    t1 = Thread(target=producer, args=(con,))
    t2 = Thread(target=consumer, args=(con,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

结果

.....
股票跌了,买入
股票涨了,卖出
股票跌了,买入
股票涨了,卖出
股票跌了,买入
股票涨了,卖出
.....

支持with操作

改造

# !/usr/bin/env python3
# -*- coding: utf-8 -*
from threading import Condition, Thread
 
con = Condition()
 
 
def producer(condition: Condition):
    while True:
        with condition:
            print("股票跌了,买入")
            condition.notify()
            condition.wait()
 
 
def consumer(condition: Condition):
    while True:
        with condition:
            print("股票涨了,卖出")
            condition.notify()
            condition.wait()
 
 
if __name__ == "__main__":
    t1 = Thread(target=producer, args=(con,))
    t2 = Thread(target=consumer, args=(con,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

备注

Condition lock参数只能传入Lock/Rlock的实例,但是其实从源码分析,python的鸭子类型决定了只要有Lock/Rlock的全部方法,目前是acquire/release方法,其实传入其他的类型也是可以,只是会有黄色警告

举个例子

我传入Semaphore也可正常运行,因为acquire/release方法Semaphore也有

# !/usr/bin/env python3
# -*- coding: utf-8 -*
from threading import Condition, Thread, Semaphore
 
sam = Semaphore(1)
con = Condition(sam)
 
 
def producer(condition: Condition):
    while True:
        with condition:
            print("股票跌了,买入")
            condition.notify()
            condition.wait()
 
 
def consumer(condition: Condition):
    while True:
        with condition:
            print("股票涨了,卖出")
            condition.notify()
            condition.wait()
 
 
if __name__ == "__main__":
    t1 = Thread(target=producer, args=(con,))
    t2 = Thread(target=consumer, args=(con,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

正常运行

这意味这什么?

Condition 是python的threading中线程模型灵活度最高的类。加入普通的Lock,可以模拟Event或者互斥锁,加入RLock可以模拟偏向锁,加入有计数功能的Lock可以模拟栅栏,加入有栈/队列功能的Lock可以模拟Semaphore.... 只要我们的鸭子类型写的正确,模型建的好,那么可以创造出各种各样的并发模型。相比Event,Barrier,Semaphore以及更低级的Lock,Condition能很好的在可塑造性和代码复杂度上取得平衡

posted @ 2021-09-26 10:42  旁人X  阅读(455)  评论(0)    收藏  举报