對於線程與線程之間的交互咱們在前面的文章已經介紹了 python 互斥鎖Lock / python事件Event , 今天繼續介紹一種線程交互方式 – 線程條件變量Condition.python
acquire() — 線程鎖,注意線程條件變量Condition中的全部相關函數使用必須在acquire() /release() 內部操做;git
release() — 釋放鎖,注意線程條件變量Condition中的全部相關函數使用必須在acquire() /release() 內部操做;github
wait(timeout) — 線程掛起(阻塞狀態),直到收到一個notify通知或者超時纔會被喚醒繼續運行(超時參數默認不設置,可選填,類型是浮點數,單位是秒)。wait()必須在已得到Lock前提下才能調用,不然會觸發RuntimeError;微信
notify(n=1) — 通知其餘線程,那些掛起的線程接到這個通知以後會開始運行,缺省參數,默認是通知一個正等待通知的線程,最多則喚醒n個等待的線程。notify()必須在已得到Lock前提下才能調用,不然會觸發RuntimeError,notify()不會主動釋放Lock;多線程
notifyAll() — 若是wait狀態線程比較多,notifyAll的做用就是通知全部線程;ide
在前面的文章已經介紹過互斥鎖,主要做用是並行訪問共享資源時,保護共享資源,防止出現髒數據。python 條件變量Condition也須要關聯互斥鎖,同時Condition自身提供了wait/notify/notifyAll方法,用於阻塞/通知其餘並行線程,能夠訪問共享資源了。能夠這麼理解,Condition提供了一種多線程通訊機制,假如線程1須要數據,那麼線程1就阻塞等待,這時線程2就去製造數據,線程2製造好數據後,通知線程1能夠去取數據了,而後線程1去獲取數據。函數
案例一:成語接龍ui
1spa 2線程 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# !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("程序結束!") |
輸出結果:
1 2 3 4 5 6 7 8 |
A:成語接龍準備好了嗎 B:準備好了~開始吧! A:一乾二淨 B:淨你妹啊,無法接...來個簡單點的... A:一天就知道看抖音美女,給你來個簡單點的,來了:毛手毛腳 B:嘿,這個我知道:腳踏實地 A:喲喲喲,不錯不錯! 程序結束! |
案例二:生產者與消費者模式,以吃火鍋爲例:一盤老肉片有10塊肉,吃完了又從新往鍋里加….
生產者:往鍋里加老肉片,每次加一盤(10塊);
消費者:吃煮熟的肉片,沒吃一片,肉片數量減一,吃完爲止;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# 導入線程模塊 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("程序結束!") |
輸出結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
肉片熟了,能夠開始吃了... 我來一塊肉片... 剩餘肉片數量:9 我來一塊肉片... 剩餘肉片數量:8 我來一塊肉片... 剩餘肉片數量:7 我來一塊肉片... 剩餘肉片數量:6 我來一塊肉片... 剩餘肉片數量:5 我來一塊肉片... 剩餘肉片數量:4 我來一塊肉片... 剩餘肉片數量:3 我來一塊肉片... 剩餘肉片數量:2 我來一塊肉片... 剩餘肉片數量:1 我來一塊肉片... 剩餘肉片數量:0 老闆,再來一份老肉片... 添加肉片成功!當前肉片數量:10 我來一塊肉片... 剩餘肉片數量:9 我來一塊肉片... 剩餘肉片數量:8 我來一塊肉片... 剩餘肉片數量:7 ............. |
注意:
1.全局變量要聲明關鍵字 global;
2.注意線程的啓動順序,這個很重要;
注意線程互斥鎖Lock/線程事件Event/線程條件變量Condition三者的區別,場景不一樣,使用方式也不一樣,前二者通常能夠做爲簡單的線程交互,線程條件變量Condition能夠用於比較複雜的線程交互!
轉載請註明:猿說Python » python條件變量Condition