python執行緒條件變數Condition(31)
對於執行緒與執行緒之間的互動我們在前面的文章已經介紹了 python 互斥鎖Lock / python事件Event , 今天繼續介紹一種執行緒互動方式 – 執行緒條件變數Condition.
一.執行緒條件變數Condition相關函式介紹
acquire() — 執行緒鎖,注意執行緒條件變數Condition中的所有相關函式使用必須在acquire() /release() 內部操作;
release() — 釋放鎖,注意執行緒條件變數Condition中的所有相關函式使用必須在acquire() /release() 內部操作;
wait(timeout) — 執行緒掛起(阻塞狀態),直到收到一個notify通知或者超時才會被喚醒繼續執行(超時引數預設不設定,可選填,型別是浮點數,單位是秒)。wait()必須在已獲得Lock前提下才能呼叫,否則會觸發RuntimeError;
notify(n=1) — 通知其他執行緒,那些掛起的執行緒接到這個通知之後會開始執行,預設引數,預設是通知一個正等待通知的執行緒,最多則喚醒n個等待的執行緒。notify()必須在已獲得Lock前提下才能呼叫,否則會觸發RuntimeError,notify()不會主動釋放Lock;
notifyAll() — 如果wait狀態執行緒比較多,notifyAll的作用就是通知所有執行緒;
二.執行緒條件變數Condition原理
在前面的文章已經介紹過互斥鎖,主要作用是並行訪問共享資源時,保護共享資源,防止出現髒資料。python 條件變數Condition也需要關聯互斥鎖,同時Condition自身提供了wait/notify/notifyAll方法,用於阻塞/通知其他並行執行緒,可以訪問共享資源了。可以這麼理解,Condition提供了一種多執行緒通訊機制,假如執行緒1需要資料,那麼執行緒1就阻塞等待,這時執行緒2就去製造資料,執行緒2製造好資料後,通知執行緒1可以去取資料了,然後執行緒1去獲取資料。
三.執行緒條件變數Condition使用
案例一:成語接龍
# !usr/bin/env python # -*- coding:utf-8 _*- """ @Author:何以解憂 @Blog(個人部落格地址): shuopython.com @WeChat Official Account(微信公眾號):猿說python @Github:www.github.com @File:python_.py @Time:2019/10/21 21:25 @Motto:不積跬步無以至千里,不積小流無以成江海,程式人生的精彩需要堅持不懈地積累! """ # 匯入執行緒模組 import threading # 建立條件變數condition con = threading.Condition() def thread_one(name): # 條件變數condition 執行緒上鎖 con.acquire() print("{}:成語接龍準備好了嗎".format(name)) # 喚醒正在等待(wait)的執行緒 con.notify() # 等待對方迴應訊息,使用wait阻塞執行緒,等待對方通過notify喚醒本執行緒 con.wait() print("{}:一乾二淨".format(name)) # 喚醒對方 con.notify() # 等待訊息答應 con.wait() print("{}:一天就知道看抖音美女,給你來個簡單點的,來了:毛手毛腳".format(name)) # 喚醒對方 con.notify() # 等待訊息答應 con.wait() print("{}:喲喲喲,不錯不錯!".format(name)) # 喚醒對方 con.notify() # 條件變數condition 執行緒釋放鎖 con.release() def thread_two(name): # 條件變數condition 執行緒上鎖 con.acquire() # wait阻塞狀態,等待其他執行緒通過notify喚醒本執行緒 con.wait() print("{}:準備好了~開始吧!".format(name)) # 喚醒對方 con.notify() # 等待訊息答應 con.wait() print("{}:淨你妹啊,沒法接...來個簡單點的...".format(name)) # 喚醒對方 con.notify() # 等待訊息答應 con.wait() print("{}:嘿,這個我知道:腳踏實地".format(name)) # 喚醒對方 con.notify() con.release() if __name__ == "__main__": # 建立並初始化執行緒 t1 = threading.Thread(target=thread_one,args=("A")) t2 = threading.Thread(target=thread_two,args=("B")) # 啟動執行緒 -- 注意執行緒啟動順序,啟動順序很重要 t2.start() t1.start() # 阻塞主執行緒,等待子執行緒結束 t1.join() t2.join() print("程式結束!")
輸出結果:
A:成語接龍準備好了嗎 B:準備好了~開始吧! A:一乾二淨 B:淨你妹啊,沒法接...來個簡單點的... A:一天就知道看抖音美女,給你來個簡單點的,來了:毛手毛腳 B:嘿,這個我知道:腳踏實地 A:喲喲喲,不錯不錯! 程式結束!
案例二:生產者與消費者模式,以吃火鍋為例:一盤老肉片有10塊肉,吃完了又重新往鍋里加….
生產者:往鍋里加老肉片,每次加一盤(10塊);
消費者:吃煮熟的肉片,沒吃一片,肉片數量減一,吃完為止;
# 匯入執行緒模組 import threading import time # 建立條件變數condition con = threading.Condition() meat_num = 0 def thread_consumers(): # 條件變數condition 執行緒上鎖 con.acquire() # 全域性變數宣告關鍵字 global global meat_num meat_num = 0 # 等待肉片下鍋煮熟 con.wait() while True: print("我來一塊肉片...") meat_num -= 1 print("剩餘肉片數量:%d"%meat_num) time.sleep(0.5) if meat_num == 0: # 肉片吃光了,通知老闆新增肉片 print("老闆,再來一份老肉片...") con.notify() # 肉片吃光了,等待肉片 con.wait() # 條件變數condition 執行緒釋放鎖 con.release() def thread_producer(): # 條件變數condition 執行緒上鎖 con.acquire() # 全域性變數宣告關鍵字 global global meat_num # 肉片熟了,可以開始吃了 meat_num = 10 print("肉片熟了,可以開始吃了...") con.notify() while True: # 阻塞函式,等待肉片吃完的通知 con.wait() meat_num = 10 # 新增肉片完成,可以繼續開吃 print("新增肉片成功!當前肉片數量:%d"%meat_num) time.sleep(1) con.notify() con.release() if __name__ == "__main__": # 建立並初始化執行緒 t1 = threading.Thread(target=thread_producer) t2 = threading.Thread(target=thread_consumers) # 啟動執行緒 -- 注意執行緒啟動順序,啟動順序很重要 t2.start() t1.start() # 阻塞主執行緒,等待子執行緒結束 t1.join() t2.join() print("程式結束!")
輸出結果:
肉片熟了,可以開始吃了... 我來一塊肉片... 剩餘肉片數量:9 我來一塊肉片... 剩餘肉片數量:8 我來一塊肉片... 剩餘肉片數量:7 我來一塊肉片... 剩餘肉片數量:6 我來一塊肉片... 剩餘肉片數量:5 我來一塊肉片... 剩餘肉片數量:4 我來一塊肉片... 剩餘肉片數量:3 我來一塊肉片... 剩餘肉片數量:2 我來一塊肉片... 剩餘肉片數量:1 我來一塊肉片... 剩餘肉片數量:0 老闆,再來一份老肉片... 新增肉片成功!當前肉片數量:10 我來一塊肉片... 剩餘肉片數量:9 我來一塊肉片... 剩餘肉片數量:8 我來一塊肉片... 剩餘肉片數量:7 .............
注意:
1.全域性變數要宣告關鍵字 global;
2.注意執行緒的啟動順序,這個很重要;
四.重點總結
注意執行緒互斥鎖Lock/執行緒事件Event/執行緒條件變數Condition三者的區別,場景不同,使用方式也不同,前兩者一般可以作為簡單的執行緒互動,執行緒條件變數Condition可以用於比較複雜的執行緒互動!
猜你喜歡:
1.python執行緒建立和引數傳遞
2.python執行緒互斥鎖Lock
3.python執行緒事件Event
4.python return邏輯判斷表示式
轉載請註明:猿說Python » python條件變數Condition
技術交流、商務合作請直接聯絡博主 掃碼或搜尋:猿說python 猿說python 微信公眾號 掃一掃關