Python中的多線程
多線程
一個進程中有多個線程就是多線程。
一個進程中至少有一個線程,并作為程序的入口,這個就是主線程。一個進程至少有一個主進程,其他線程稱為工作線程。
線程安全:線程執行一段代碼,不會產生不確定的結果,那這段代碼就是線程安全。(例如print()線程不安全)
線程的daemon屬性
daemon屬性:表示線程是否是daemon線程,這個值必須在start()之前設置,否則引發RuntimeError異常
isDaemon():是否是daemon線程
setDaemon():設置為daemon線程,必須在start方法之前設置
線程具有一個daemon屬性,可以設置為Ture或False,也可以不設置,默認值為None.如果不設置daemon就取當前的daemon來設置它,主線程是Non-daemon。工作線程不設置daemon屬性,則默認是daemon = False .python程序在沒有活著的non-daemon線程運行時退出。
join()方法
join(timeout)是線程的標準方法之一。
一個線程中調用里那個一個線程的join方法,調用者將被阻塞,知道盜用線程終止。一個線程可以被join多次。
daemon線程的應用場景
1:后臺任務,如發送心跳包、監控,這種場景最多
2:主線程工作才有用的線程,如主線程中維護的公共資源,主線程已經清理了,準備退出,而工作線程使用這些資源工作也沒有意義了,一起退出最合適。
3:隨時可以被終止的線程
threading.local類
運行時,threading.local實例處在不同的線程中,就從大字典中找到當前線程相關鍵值對中的字典,覆蓋threading.local實例的__dict__。這樣就可以在不同的線程中,安全德使用線程獨有的數據做到線程間數據隔離,如同本地變量一樣安全。
定時器Timer/延遲執行
threading.Timer(interval,function,args=None,Kwargs=None)
start方法執行之后,Timer對象會處于等待狀態,等待了interval秒之后,開始執行function函數的。Timer提供了cancel方法,用來取消一個未執行的函數。
Event
是線程間通信機制中最簡單的實現,使用一個內部的標記flag,通過flag的True或False的表換來進行操作。
set():標記設置為Ture
clear():標記設置為False
is_set():標記是否為Ture
wait(timeou):設置等待標記為Ture的時長,None為無限等待,等到返回Ture,未等到超時了返回False
Event的wait優于time.sleep,他會更快的切換到其它線程,提高并發效率。
lock
鎖,凡是存在共享資源爭搶的地方都可以使用鎖,從而保證只有一個使用者可以完全使用這個資源。一旦線程獲得鎖,其他試圖獲取鎖的線程將被阻塞。
acquire(blocking=True,timeout=-1):默認阻塞,阻塞可以設置超時時間,非阻塞時,timeout禁止設置。成功獲取鎖,返回True,否則返回Flase
release():釋放鎖,可以從任何線程調用釋放。已上鎖的多,會被重置未unlocked。未上鎖的調用,會派出RuntimeError異常。
加鎖、解鎖
一般來說,加鎖就需要解鎖,但加鎖后解鎖前,還有一些代碼執行,就有可能拋出異常,一旦出現異常,鎖無法釋放,但是當前線程可能因為這個異常被終止了,這就產生了死鎖。
加鎖、解鎖常用的語句:
1:使用try ... funally語句保證鎖的釋放
2:with上下文管理,鎖隨想支持上下位管理。
鎖的應用:
鎖適合用于訪問和修改同一個共享資源的時候,即讀寫同一個資源的時候。
注意事項:
1:少用鎖,必要時使用鎖,使用了鎖,多線程訪問被鎖的資源時,就成了串行,要么排隊執行,要么爭搶執行。
2:加鎖時間越短越好,不需要就立即釋放。
3:一定要避免死鎖。
Rlock可重入鎖
可重入鎖,是線程相關的鎖??稍谝粋€線程中獲取鎖,并可繼續在同一個線程中不阻塞獲取鎖,當鎖為釋放完,其他線程獲取鎖就會阻塞。知道當前持有鎖的線程釋放完鎖。
Conditon
構造方法Consition(lock=None),可以傳入一個Lock或者Rlock對象,默認是Rlock
acquire(*args):獲取鎖
wait(self.timeout=None):等待或超時
notify(n =1):喚醒至多指定數目個數的等待的線程,沒有線程等待的線程就沒有任何操作
notify_all():喚醒所有等待的線程
condition用于生產者,消費者模型,為了解決生產者消費者速度匹配的問題。由于condition內部使用了鎖,最好的方式是使用with上下文。
Barrier
Barrier(parties,action=None,timeout=None):構建Barrier對象,指定參與方數目。timeout是wait方法未指定超時的默認值。
n_waiting:當前在barrier中等待的線程數
parties:資源的個數。
broken:如果broken處于打破的狀態,放回True
abort():將將barrier置于broken狀態,等待中的線程或者調用等待方法的線程中都會拋出BrokenBarrierError異常,知道reset方法來恢復barrier
reset():恢復barrier,重新開始攔截。
wait方法超時發生,barrier將處于broken狀態,知道reset()
semaphore信號量
Semaphore(value=1):構造方法,value小于0,拋ValueError異常
acquite(blocking=True,timeout=None):獲取信號量,計數器減1,獲取成功返回True
release():釋放信號量,計數器加1
semaphore問題
如果遇到release釋放次數大于初始值,計數器會增加,超過我們的最大值。
解決方法:
使用Boundedsemaphore類,有界信號量,不允許使用release超出初始值的范圍,否則派出ValueError異常。
鎖和信號量
鎖,只允許同一個時間一個線程獨占資源,它是特殊的信號量,即信號量計數器初始值為1.
信號量,可以多個線程訪問共享資源,但這個共享資源數量有限。
鎖,可以看做特殊的型號量。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。