class threading.Condition(lock=None
這個類實現條件變量對象。條件變量容許一個或多個線程等待,知道它們被另外一個線程喚醒。
若是給出了lock
參數而不是None
,則它必須是Lcok
或RLock
對象,並以它做爲底層的鎖。不然將默認建立一個RLock
對象。
Condition
遵循上下文管理協議。
方法:
acquire(*args)
獲取鎖。這個方法調用底層鎖的相應方法。python
release()
釋放鎖。這個方法調用底層鎖的相應方法。併發
wait(timeout=None)
線程掛起,等待被喚醒(其餘線程的notify
方法)或者發生超時。調用該方法的線程必須先得到鎖,不然引起RuntimeError
。
該方法會釋放底層鎖,而後阻塞,直到它被另外一個線程中的相同條件變量的notify()
或notify_all()
方法喚醒,或者發生超時。一旦被喚醒或超時,它會從新獲取鎖並返回。
返回值爲True
,若是給定timeout
併發生超時,則返回False
。ui
wait_for(predicate, timeout=None)
等待知道條件變量的返回值爲True
。predicate
應該是一個返回值能夠解釋爲布爾值的可調用對象。能夠設置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()
,但喚醒的時全部等待的線程。對象
場景:生產者一次性生產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沒錢了-回老家