Python並行編程(四):多線程同步之condition(條件變量)實現帶有緩衝區的生產者-消費者模型

什麼是Condtion?

所謂condition條件變量,即這種機制是在知足了特定的條件後,線程才能夠訪問相關的數據。 這種同步機制就是一個線程等待特定的條件,另外一個線程通知它條件已經發生。一旦條件發生,該線程就會獲取鎖,從而獨佔共享資源的訪問。 Condition包含如下部分:python

  • c.acquire(*args):獲取底層鎖。此方法將調用底層鎖上對應的acquire(*args)方法。
  • c.release():釋放底層鎖。此方法將調用底層鎖上對應的release()方法
  • c.wait(timeout):等待直到獲取通知或出現超時爲止。此方法在調用線程已經獲取鎖以後調用。 調用時,將釋放底層鎖,並且線程將進入睡眠狀態,直到另外一個線程在條件變量上執行notify()notify_all()方法將其喚醒爲止。在線程被喚醒後,線程講從新獲取鎖,方法也會返回。timeout是浮點數,單位爲秒。 若是超時,線程將被喚醒,從新獲取鎖,而控制將被返回。
  • c.notify(n):喚醒一個或多個等待此條件變量的線程。此方法只會在調用線程已經獲取鎖以後調用, 並且若是沒有正在等待的線程,它就什麼也不作。 n指定要喚醒的線程數量,默認爲1.被喚醒的線程在它們從新獲取鎖以前不會從wait()調用返回。
  • c.notify_all():喚醒全部等待此條件的線程。

通俗的解釋:函數

Python提供的Condition對象提供了對複雜線程同步問題的支持。Condition被稱爲條件變量,除了提供與Lock相似的 acquire和release方法外,還提供了wait和notify方法。線程首先acquire一個條件變量,而後判斷一些條件。若是條件不知足則 wait;若是條件知足,進行一些處理改變條件後,經過notify方法通知其餘線程,其餘處於wait狀態的線程接到通知後會從新判斷條件。不斷的重複 這一過程,從而解決複雜的同步問題。 能夠認爲Condition對象維護了一個鎖(Lock/RLock)和一個waiting池。線程經過acquire得到Condition對 象,當調用wait方法時,線程會釋放Condition內部的鎖並進入blocked狀態,同時在waiting池中記錄這個線程。當調用notify 方法時,Condition對象會從waiting池中挑選一個線程,通知其調用acquire方法嘗試取到鎖。 Condition對象的構造函數能夠接受一個Lock/RLock對象做爲參數,若是沒有指定,則Condition對象會在內部自行建立一個RLock。ui

帶有緩衝區的生產者-消費者模型

咱們能夠根據所謂的wait池構建一個帶有緩衝區的生產者-消費者模型,即緩衝區比如一個倉庫,生產者能夠不斷生產商品知道倉庫裝滿,而後告知消費者消費,而消費者也能夠判斷倉庫是否滿了從而告知生產者繼續生產商品:spa

import threading
import time

# 假設商品數量
goods = 0

condition = threading.Condition()


def consumer():
    global goods
    while True:
        condition.acquire()
        if goods <= 0:
            # 倉庫空了,即特定條件知足了,通知生產者生產
            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:
            # 倉庫滿了,即特定條件知足了,通知消費者消費
            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.')

複製代碼

運行截圖以下: 線程

運行結果
相關文章
相關標籤/搜索