1. 程式人生 > >python中的threading模組使用說明

python中的threading模組使用說明

這段時間使用python做串列埠的底層庫,用到了多執行緒,對這部分做一下總結。實際用完了後再回過頭去看python的官方幫助文件,感覺受益匪淺,把裡面的自己覺得有用的一些關鍵點翻譯出來,留待後續查驗。
threading是thread的高階介面模組,包括了除了thread模組,還有mutex模組、queue模組、dummy_threading模組方面的內容。
該模組定義了一下幾方面的函式和物件:
threading.activeCount() :返回現存在活動狀態的執行緒數。返回的數目等於enumerate()列表的長度。
threading.Condition():是返回一個新的condition變數型別的工廠函式(返回物件的函式)。一個condition型別的變數允許一個或多個執行緒等待,直到被另一個執行緒通知。
threading.currentThread() :根據使用者執行緒控制代碼,返回當前的執行緒物件。如果執行緒控制代碼並未通過threading模組建立,有限功能的啞執行緒會被建立。
threading.enumerate() :返回所有活動執行緒物件列表。包括守護執行緒、由current_thread()建立的啞執行緒以及主執行緒。不包括終止了的執行緒和未開始的執行緒。
threading.Event() :是返回一個新的event型別的工廠函式。一個event管理一個標識,可以使用set()方法設定為true,也可以由clear()方法重置為false。wait()方法會阻塞直到這個標識為true。
class threading.local:代表執行緒本地資料的類。執行緒本地資料是該執行緒獨有的。通過建立一個local例項,可以管理執行緒本地資料,並且能儲存其屬性。如:
mydata = threading.local()
mydata.x = 1
該屬性的值因執行緒不同而異。


threading.Lock() :是一個返回新的單鎖物件的工廠函式。只要一個執行緒獲取該鎖,相關其他要獲取該鎖的執行緒都會阻塞,直到鎖被釋放。任何執行緒都可以釋放它。
eg:
testLock=threading.Lock()
testLock.acquire()#對鎖的使用,也可以不用acquire()和release,直接使用with testLock:即可
self._test=True
testLock.release()
(注意:互斥鎖用來鎖定不同執行緒中的互斥量,鎖的內容儘可能簡潔,只鎖定必須互斥的部分,以節省執行緒運轉的時間)
threading.RLock() :返回一個可重入鎖的工廠函式。可重入鎖必須由建立它的執行緒釋放。一旦一個執行緒獲取了一個可重入鎖,同一執行緒內可以繼續獲取它而不阻塞。執行緒獲取了幾次可重入鎖,必須釋放同樣的次數。
(在此次專案實踐中,重鎖沒有用到,但知道了這樣的場景,即同一執行緒,如果鎖中間呼叫的函式,有用到同樣的鎖,如果用單鎖,會發生死鎖,而用可重入鎖,不會發生阻塞,可以防止這樣場景下的死鎖。)
threading.Semaphore([value]) :是返回一個新的訊號量物件的工廠函式。訊號量管理一個計數器,代表呼叫release()的個數減去呼叫acquire(),再加上初始值的數目。當該值為負數時,acquire()方法會阻塞。value的預設值是1。
(當時考系統分析師,對於訊號量總是理解的很抽象,其實就是控制執行緒同步和互斥量的。當初建立這一概念的科學家使用p()和V()取代了acquire()和release()。訊號量管理一個內部計數器,每呼叫一個acquire()就遞減一次,每呼叫release()就遞增一次。這個計數器不能小於0。一旦呼叫acquire()時發現它小於0,則執行緒阻塞,直到其他執行緒呼叫release()。)


class threading.Thread:代表執行緒控制代碼的類。
threading用於提供執行緒相關的操作,執行緒是應用程式中工作的最小單元。python當前版本的多執行緒庫沒有實現優先順序、執行緒組,執行緒也不能被停止、暫停、恢復、中斷。
thread是執行緒類,有兩種使用方法,直接傳入要執行的方法(推薦,簡便)或從thread繼承並覆蓋run()。一旦執行緒物件被建立,必須呼叫執行緒的start()方法開始執行緒。這一操作會喚醒每個執行緒的run()方法。當執行緒開始後,這個執行緒被認為是活動的。當它的run()方法終結,執行緒就結束了,或者通常的做法是,是觸發一個不能處理的異常。可以用is_alive()方法判斷執行緒是否活動。
其他執行緒可以呼叫某個執行緒的join()方法。這會阻塞當前上下文環境的執行緒,直到呼叫此方法的執行緒終止。
一個執行緒可以被標識為“守護執行緒”。當所有子執行緒為守護執行緒時,如果主執行緒結束,則所有子執行緒也就結束了。比較優雅的退出方法是引入event丟擲異常。
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
group:必須是none,留待後續擴充套件應用。
target:被呼叫的函式物件
name:執行緒名,可預設不填,由系統自動建立
args:呼叫函式物件的傳參,是一個元祖型別
kwargs:函式傳參,是字典型別
如果子類過載了此建構函式,必須在對此執行緒操作之前,在子類中顯式呼叫建構函式(thread.__init__())
start():每個執行緒中只能最多呼叫一次,否則會丟擲執行錯誤。
run():在子類中過載此方法。
join([timeout]):等待直到執行緒終結。這會阻塞當前上下文環境的執行緒,直到呼叫此方法的執行緒終止或超時。
(因此當所有子執行緒結束後,主執行緒才會結束)
isAlive():返回該執行緒是否活動。
daemon:setDaemon()必須線上程啟動start()之前呼叫,否則會丟擲執行錯誤異常。


condition物件:一個condition物件通常和某種鎖關聯。condition變數擁有acquire()和release()方法,可呼叫相應的鎖。還有wait()方法,notify()方法和notifyall()方法,但這三種方法必須在獲取到鎖之後進行,否則會丟擲執行錯誤異常。
class threading.Condition([lock]) :如果引數lock給出,必須是Lock或RLock的物件。
acquire(*args):獲取一個基礎鎖。
release() :釋放鎖
wait([timeout]) :等待,直到被通知或者超時。如果執行緒沒有獲取到鎖,而呼叫了這個方法,則會丟擲執行錯誤異常。
此訊息會釋放基礎鎖,然後阻塞直到因為在另一執行緒的同樣的condition變數被notify或notifyAll()喚醒,一旦喚醒或超時,會重新獲取鎖並返回(好拗口,直白的意思就是“我累了,休息會兒,資源你們先拿去用”,然後要等待其他獲取鎖的執行緒,呼叫條件變數的notify或者nofityAll方法,才能把原有等待的執行緒喚醒繼續執行)。
如果鎖是一個可重入鎖,並不能通過release方法被釋放,原因是當它被鎖了好多次的時候,這可能並沒有真的解開鎖。然而,一個可重入鎖磊的內部介面被使用,這可以真的解開鎖即便鎖被獲取了多次。
notify(n=1):預設情況下,喚醒一個等待的情況變數。


Event物件:這是最簡單的執行緒間通訊機制之一:一個執行緒釋放一個event事件,而其他執行緒捕捉它。
一個event物件管理一個內部標識可以通過set()方法設為true,也可以通過clear()方法設為false。wait()方法會阻塞,直到該標識為True。預設是False
set():設定該標識為True。所有等待它為True的執行緒會被喚醒。呼叫wait()的執行緒,一旦該標識為True就不會再阻塞。
clear():設定該標識為false。相應地,呼叫wait的執行緒會阻塞,直到呼叫set方法把標識設為true
wait():當內部標識為true時阻塞。如果該內部標識一開始就是true,直接返回。否則,會阻塞知道其他執行緒呼叫se()把標識設為true,或者直到可選的超時發生。