什么是Condtion?
所謂condition條件變量,即這種機(jī)制是在滿足了特定的條件后,線程才可以訪問相關(guān)的數(shù)據(jù)。 這種同步機(jī)制就是一個(gè)線程等待特定的條件,另一個(gè)線程通知它條件已經(jīng)發(fā)生。一旦條件發(fā)生,該線程就會(huì)獲取鎖,從而獨(dú)占共享資源的訪問。
Condition包含以下部分:
- c.acquire(args):獲取底層鎖。此方法將調(diào)用底層鎖上對(duì)應(yīng)的acquire(args)方法。
- c.release():釋放底層鎖。此方法將調(diào)用底層鎖上對(duì)應(yīng)的release()方法
- c.wait(timeout):等待直到獲取通知或出現(xiàn)超時(shí)為止。此方法在調(diào)用線程已經(jīng)獲取鎖之后調(diào)用。
調(diào)用時(shí),將釋放底層鎖,而且線程將進(jìn)入睡眠狀態(tài),直到另一個(gè)線程在條件變量上執(zhí)行notify()或notify_all()方法將其喚醒為止。在線程被喚醒后,線程講重新獲取鎖,方法也會(huì)返回。timeout是浮點(diǎn)數(shù),單位為秒。
如果超時(shí),線程將被喚醒,重新獲取鎖,而控制將被返回。 - c.notify(n):?jiǎn)拘岩粋€(gè)或多個(gè)等待此條件變量的線程。此方法只會(huì)在調(diào)用線程已經(jīng)獲取鎖之后調(diào)用,
而且如果沒有正在等待的線程,它就什么也不做。
n指定要喚醒的線程數(shù)量,默認(rèn)為1.被喚醒的線程在它們重新獲取鎖之前不會(huì)從wait()調(diào)用返回。
c.notify_all():?jiǎn)拘阉械却藯l件的線程。
通俗的解釋:
Python提供的Condition對(duì)象提供了對(duì)復(fù)雜線程同步問題的支持。Condition被稱為條件變量,除了提供與Lock類似的 acquire和release方法外,還提供了wait和notify方法。線程首先acquire一個(gè)條件變量,然后判斷一些條件。如果條件不滿足則 wait;如果條件滿足,進(jìn)行一些處理改變條件后,通過notify方法通知其他線程,其他處于wait狀態(tài)的線程接到通知后會(huì)重新判斷條件。不斷的重復(fù) 這一過程,從而解決復(fù)雜的同步問題。
可以認(rèn)為Condition對(duì)象維護(hù)了一個(gè)鎖(Lock/RLock)和一個(gè)waiting池。線程通過acquire獲得Condition對(duì) 象,當(dāng)調(diào)用wait方法時(shí),線程會(huì)釋放Condition內(nèi)部的鎖并進(jìn)入blocked狀態(tài),同時(shí)在waiting池中記錄這個(gè)線程。當(dāng)調(diào)用notify 方法時(shí),Condition對(duì)象會(huì)從waiting池中挑選一個(gè)線程,通知其調(diào)用acquire方法嘗試取到鎖。
Condition對(duì)象的構(gòu)造函數(shù)可以接受一個(gè)Lock/RLock對(duì)象作為參數(shù),如果沒有指定,則Condition對(duì)象會(huì)在內(nèi)部自行創(chuàng)建一個(gè)RLock。
帶有緩沖區(qū)的生產(chǎn)者-消費(fèi)者模型
我們可以根據(jù)所謂的wait池構(gòu)建一個(gè)帶有緩沖區(qū)的生產(chǎn)者-消費(fèi)者模型,即緩沖區(qū)好比一個(gè)倉庫,生產(chǎn)者可以不斷生產(chǎn)商品知道倉庫裝滿,然后告知消費(fèi)者消費(fèi),而消費(fèi)者也可以判斷倉庫是否滿了告知生產(chǎn)者繼續(xù)生產(chǎn)商品:
import threading
import time
# 假設(shè)商品數(shù)量
goods = 0
condition = threading.Condition()
def consumer():
global goods
while True:
condition.acquire()
if goods <= 0:
# 倉庫空了,即特定條件滿足了,通知生產(chǎn)者生產(chǎn)
condition.notify()
condition.wait()
time.sleep(2)
goods -= 1
print('consume 1, left {}'.format(goods))
time.sleep(2)
condition.release()
def producer():
global goods
while True:
condition.acquire()
if goods >= 5:
# 倉庫滿了,即特定條件滿足了,通知消費(fèi)者消費(fèi)
condition.notify()
condition.wait()
time.sleep(2)
goods += 1
print('produce 1, already {}'.format(goods))
time.sleep(2)
condition.release()
if __name__ == '__main__':
thread_consumer = threading.Thread(target=consumer)
thread_producer = threading.Thread(target=producer)
thread_consumer.start()
thread_producer.start()
thread_consumer.join()
thread_producer.join()
print('consumer-producer example end.')
運(yùn)行截圖如下:
