python多线程模块_python 多线程模块参考
threading.active_count()
返回當前處于 active 狀態的線程的數目
threading.current_thread()
返回調用者當前的 Thread 對象
threading.get_ident()
返回當前線程的“thread identifier”屬性(3.3新增)
threading.enumerate()
返回當前處于 active 狀態的線程組成的列表
threading.settrace(func)
為所有從 threading 模塊生成的線程添加 trace function
threading.setprofile(func)
為所有從 threading 模塊生成的線程添加 profile function
threading.stack_size([size])
返回創建線程時分配的??臻g大小,或通過參數進行設定
注:上面有個別函數是無法通過“from threading import *”導入的,必須通過“.”來訪問。
本模塊含有如下常量:
threading.TIMEOUT_MAX
此常量限定 timeout 參數的最大值,超則OverflowError(3.2新增)
本模塊還含有如下類:
1. Thread-Local Data
Thread-Local data 用于存放“線程區分”的數據。要想使用它,只須創建一個 local 類實例(或子類)然后在它的屬性里存儲數據。不同線程訪問該實例的屬性值,是不同的。
>>> mydata = threading.local()
>>> mydata.x = 1
>>> type(mydata)
2. Thread Objects
Thread 類用來實現子線程。有兩種方法來使用它:
給構造器傳一個可調用對象(可以是函數,也可以是覆蓋了 __call__() 方法的類實例)
子類化 Thread 類,并覆蓋 run() 方法
即,除了 __init__() 和 run() 以外,不要覆蓋此類的其他任何方法。
在創建了 Thread 對象后,通過調用它的 start() 方法,run() 方法的內容會在一個新線程里被執行。
一旦一個線程開始執行,那么他就處于“alive”的狀態,除非 run() 方法執行完畢,或引發了一個未處理的異常。Thread 對象的 is_alive() 方法可以用來檢測對象當前的狀態。
線程A 可以調用線程B 的 join() 方法,調用后線程A 會被掛起,直到線程B 結束。
每個線程都有自己的名字。可以在調用構造器時通過 name=None 來設定,或者實例化后通過 name 屬性來訪問
線程可以被標記為“daemon thread”,這表示主程序可以不管他們死活。。。我是說,當一個程序里只剩下“daemon thread”沒有結束時,程序就會直接退出。這個標記可以通過對象的 setDaemon() 方法來設定,但一定要在調用 start() 之前。對象的 daemon 屬性和 isDaemon() 方法都可以用來檢查它的標記。
Python 程序的初始線程叫做“main thread”,當然他肯定不是“daemon thread”:
>>> threading.current_thread()
<_MainThread(MainThread, started 1808)>
>>> threading.current_thread().name
'MainThread'
>>> type(threading.current_thread())
值得一提的是,程序中有可能出現一種叫“dummy thread objects”的對象,他們一般在 threading 模塊之外被創建,比如直接運行的 C 代碼,“dummy thread objects”只有有限的功能;他們永遠被認為是“alive”的,而且不能夠被 join()??紤]到 Python 無法檢測到他們到底處于什么狀態,那么他們也就永遠不會被刪除。
class threading.Thread(group=None,target=None,name=None,args=(),kwargs={},*,daemon=None)
請只使用關鍵字參數調用本構造器
group 應為 None,這參數是為將來可能出現的 ThreadGroup 類準備的(現在還沒有實現)
target 為將被 run() 方法調用的可調用對象。如果是 None,那就意味著什么也不做
name 是本線程的名字,默認會分配一個形如“Thread-N”的名字,其中 N 是一個十進制數
args 是給 target 準備的非關鍵字參數
kwargs 是給 target 準備的關鍵字參數
daemon 用來設定線程的 daemon 屬性,如果使用默認值(None),將從當前進程中繼承
如果 Thread 的子類重寫了構造函數,那么一定要確保在子類構造函數的第一行先調用父類的構造函數(Thread.__init__())
Thread 類的屬性和方法:
start()
開始線程的執行
本方法至多只能調用一次。它會在獨立線程中執行 run() 方法
如果對一個對象多次調用本方法,會引發 RuntimeError 異常
run()
包含了線程實際執行的內容
本方法可以在子類中覆蓋。否則默認調用傳給構造器的 target 參數(和 args,kwargs 參數)
join(timeout=None)
被調用 join() 方法的線程會一直阻塞調用者的線程,直到自己結束(正常結束,或引發未處理異常),或超出 timeout 的時間
timeout 參數是一個以秒為單位的浮點數。當給出 timeout 參數時,因為 join() 方法總是返回 None,你應該隨即調用 is_alive() 方法,來判斷子線程到底是終結了,還是超時了。
如果沒有給出 timeout 參數,那么調用者的進程會一直阻塞到本進程結束
一個線程可以被 join() 多次
當調用 join() 方法可能引發死鎖,或被調用者的進程還未 start() 時,都會引發一個 RuntimeError
name
用于鑒別進程的一個字符串,沒啥特別的意義。不同進程的 name 可以相同,初始值由構造器給出
getName() / setName()
為后向兼容而保留的方法,現在請直接通過 name 屬性來訪問
ident
本線程的“thread identifier”,如果線程還未開始,則值為 None。這是一個非零的整數。當進程結束,另一個新的進程開始時,本 id 可能會被回收。本 id 即使在進程結束后仍然有效
is_alive()
返回本進程是否是 alive 狀態
daemon
布爾值,標明本進程是否為“daemon thread”。一定要在 start() 被調用前設定,否則引發 RuntimeError。初始值繼承自當前線程,因此從主線程創建的子線程默認都是 False,而從“daemon thread”創建的子線程默認都是 True
當只剩下“daemon thread”為 alive 狀態時,整個程序就會退出
isDaemon() / setDaemon()
為后向兼容而保留的方法,現在請直接訪問 daemon 屬性
3. Lock Objects
原語鎖(synchronization primitive,也叫同步數據結構鎖、互斥鎖、二值信號量)是一種對所有線程開放訪問的同步原語。它是現今 Python 中最低級的同步原語,直接由 _thread 模塊實現。
原語鎖總是處于”locked”或者“unlocked”兩種狀態之一,初始默認為“unlocked”狀態。它有兩個基本方法:acquire() 和 release()。在“unlocked”狀態下調用 acquire(),原語鎖會進入“locked”狀態并立即返回一個“True”;但如果是在“locked”狀態下嘗試調用 acquire(),調用者的線程會阻塞,直到該原語鎖被其他線程釋放,然后阻塞的 acquire() 立即將鎖轉換到“locked”狀態并返回值。 release() 方法不能在“unlocked”狀態下調用,否則會引發 RuntimeError 異常。
鎖對象同樣支持“上下文管理協議”。
假如有多個線程因為試圖調用一個“locked”狀態的鎖的 acquire() 方法而被阻塞住,那么在該鎖被釋放后只會有一個線程能夠成功獲取到這個鎖,至于是哪一個鎖,這不受我們控制,而且沒有規律。
兩個方法的執行都是原語級的。
class threading.Lock
本類用于實現原語鎖對象。當一個鎖被某個線程獲取到時,其它試圖再獲取本鎖的線程都會阻塞,直到本鎖被釋放掉,任何線程都可以調用 release()方法。
Python3.3 中,Lock 從一個工廠函數轉換成了一個類
Lock 類包含的方法:
acquire(blocking=True,timeout=-1)
以阻塞或非阻塞的方式獲取一個鎖
當 blocking 參數為 True(默認)時,調用者的線程會阻塞直到鎖轉為“unlocked”狀態,隨即將之設為“locked”狀態并返回 True
當 blocking 參數為 False 時,則不會阻塞。但如果 acquire() 失敗(鎖已經是 locked狀態),則會立即返回一個 False,并繼續執行線程
當 timeout 參數為一個正的浮點數時,若發生阻塞,則至多阻塞 timeout 秒;若為 –1 (默認值),則表示會一直阻塞下去。(注:模塊內的 TIMEOUT_MAX 常量僅限制設定 timeout 參數時的最大值,并不會限制“無限阻塞”這種狀況的執行)另外不允許當 blocking=False 時設置 timeout 參數。
本方法在獲取成功時返回 True,失敗則返回 False,比如說 timeout 超時
3.2 新增:timeout 參數
3.2 新增:現在 Lock.acquire() 可以被 POSIX 的信號中斷
release()
釋放一個鎖,本方法可以在任何線程內調用,不限定獲得鎖的那個線程
當鎖處于“locked”狀態時,本方法將之重置為“unlocked”狀態,并返回(None)。如果有其他線程在等待本鎖解鎖,則只有其中一個線程可以成功獲取到本鎖
若調用一個“unlocked”鎖的本方法,則會引發一個 RuntimeError 異常
本方法無返回值(None)
4. RLock Objects
可重入鎖是一種可以由同一個線程多次獲取的同步原語?;蛘哒f,它使用“owning thread”和“recursion level”的概念(后面譯作“綁定線程”和“遞歸等級”)來擴充原語鎖的“locked/unlocked”狀態。在“locked”狀態下,可重入鎖是綁定到某個線程的,“unlocked”狀態下不綁定任何線程
調用鎖的 acquire() 方法就可以將該鎖鎖住,一旦線程綁定到該鎖上就立即返回。調用鎖的 release() 方法可以解鎖。acquire() / release() 調用是成對的,只有最終(最外層)的 release() 調用可以將鎖重置到“unlocked”狀態,并允許其他線程再次獲取該鎖
可重入鎖同樣支持“上下文管理協議”
class threading.RLock
本類用于實現可重入鎖對象。可重入鎖只能被獲取到它的那個線程釋放。一旦一個線程獲取到了一個可重入鎖,這個線程就可以再次獲取這個鎖,該線程獲取了多少次,最后就得釋放多少次
注意 RLock 其實是一個工廠函數,他總是返回一個當前平臺下最高效的一個 RLock 版本
RLock 類包含的方法:
acquire(blocking=True,timeout=-1)
以阻塞或非阻塞的方式獲取一個鎖
無參數調用時:如果線程已經綁定到這個鎖上,則遞歸等級 +1,然后立即返回。如果是非綁定的其他線程,則阻塞直到鎖狀態置為“unlocked”。當鎖的狀態變為“unlocked”時(沒有綁定到任何一個線程),立即綁定該鎖,將遞歸等級設為 1,然后返回。如果有多個線程在等待獲取鎖,則只會有一個能夠成功獲得
顯式設定 blocking=True 時,和無參數的狀況相同
顯示設定 blocking=False 時,調用本方法的進程不會阻塞,但如果獲取失敗,則會返回一個 False。
當 timeout 參數為一個正的浮點數時,若發生阻塞,則至多阻塞 timeout 秒;若最后獲取成功則返回 True,超時則返回 False
3.2 新增:timeout 參數
release()
用于釋放一個鎖,功能為將遞歸等級減 1 。當遞歸等級減到 0 時,鎖就被置為“unlocked”狀態(不被任何線程綁定)。這時如果有其他線程在等待獲取這個鎖,那么其中只能有一個能夠成功。如果遞歸等級減 1 后仍不為零,則保持“locked”狀態,和與原線程的綁定關系
本方法只能被綁定的線程調用,否則引發 RuntimeError 異常
本方法無返回值(None)
5. Condition Objects
條件變量(condition variable)總是和鎖聯用的;你可以親自給它傳遞一個鎖,或者默認情況下它也可以自動生成。手動傳的狀況一般發生在多個條件變量要共享同一個鎖的時候,條件變量的鎖可以看成它自己的一部分
條件變量支持上下文管理協議:with 語句會獲取關聯鎖。acquire() 和 release() 方法也會調用關聯鎖的對應方法
條件變量的其他方法只能在已獲取到鎖的情況下調用。wait() 方法會釋放鎖,并阻塞直到其他線程通過 notify() 或 notify_all() 方法喚醒他。一旦被喚醒后,wait() 方法將從新獲取鎖并返回。
notify() 和 notify_all() 方法用于喚醒正處于等待狀態的線程。
注意:notify() 和 notify_all() 方法并不會釋放鎖;這即是說被喚醒的線程的 wait() 方法并不能立即返回,只能等到調用 notify() 方法的線程主動釋放鎖之后
使用條件變量的典型編程風格是通過鎖去同步對某些公共狀態的訪問,關注某種狀態變化的線程可以重復調用 wait() 方法直到觀察到狀態改變,而有機會改變某種狀態的線程則可以在每次改變狀態后就主動通過 notify() 方法去喚醒等待的線程一次,至于狀態是否已經變更為等待線程需要的結果,那由等待線程自己去檢查。
舉個栗子,下面的代碼是一個普通的帶有無限緩沖容量的 生產者-消費者 環境:
#consume one item
with cv:
while not an_item_is_available():
cv.wait()
get_ab_avilable_item()
#produce one item
with cv:
make_an_item_available()
cv.notify()
這里使用了 while 循環是因為 wait() 函數會在被喚醒后返回,而此時 an_item_is_available() 的值未必為 True。這種狀況是多線程編程固有的。不過也可以使用 wait_for() 方法來自動檢查狀態:
#consume an item
with cv:
cv.wait_for(an_item_is_available)
get_an_available_item()
notify() 和 notify_all() 之間的選擇可視具體狀況而定,即是否有多條線程正在等待此狀態的改變。比方說,在一個典型的 生產者-消費者 環境下,往緩沖區添加一個對象,一般只需要喚醒一個消費者線程
class threading.Condition(lock=None)
本類用于實現條件變量對象。條件變量對象允許多條線程保持等待狀態直到接收另一條線程的通知。
如果選擇傳入 lock 參數,只能使用 Lock 或 RLock 對象,而且它會被當做一個隱性鎖使用。如果不傳此參數,那么程序會自動隱性地創建一個 RLock 對象。
Python 3.3 起,Condition 從工廠函數轉變為類
Condition 類包含的方法:
acquire(*args)
本方法用于獲取隱性鎖(關聯鎖),它調用隱性鎖的 acquire() 方法,并返回其所返回的值
release()
同上,本方法無返回值
wait(timeout=None)
等待通知或超時。如果線程沒有獲取到鎖就調用了此方法,那么將引發 RuntimeError 異常
本方法會釋放隱性鎖,然后阻塞直到被其他線程的調用此條件變量的 notify() 或 notify_all() 喚醒,或超時。一旦被喚醒或超時,該線程將立即重新獲取鎖并返回
timeout 參數是以秒為單位的浮點數
如果隱性鎖是一個 RLock 對象,因為調用它的 release() 方法未必能夠釋放該鎖,所以本方法會使用 RLock 對象的一個內部接口,該接口可以立即釋放多重迭代的 RLock 鎖。并且在需要重新獲取鎖的時候,也會使用一個類似的內部接口來恢復多重的迭代級別
本方法所阻塞的線程如果是被喚醒的,那么本方法會返回一個 True,如果是超時了,則返回 False
wait_for(predicate,timeout=None)
等待直到某個條件的值為 True。predicate 是一個返回可布爾化值的可調用對象。timeout 參數是可選的
本方法可能會多次調用 wait() 直到 predicate 為真,或超時。本方法的返回值為最后一次調用 predicate 的返回值,除非超時,超時的時候返回 False
不考慮 timeout 參數,調用此方法基本等價于:
while not predicate():
cv.wait()
因此,對于 wait() 的那一套規則在本方法內也適用:沒有獲取鎖的線程不能調用本方法。
本方法為 3.2 新增
notify(n=1)
本方法默認用于喚醒處于等待本條件變量的線程。如果調用本方法的線程并沒有獲得鎖,將引發 RuntimeError 異常
本方法至多可喚醒所有正在等待本條件變量的線程中的 n 個。如果調用時沒有線程處于等待操作,那么本方法的調用是一個空操作
現在版本對本方法的實現為:在有足夠多處于等待狀態的線程的條件下,本方法將正好喚醒其中的 n 個,而不是像上一條中講的“至多 n 個”。不過這種行為并不可靠。在將來,本方法很可能偶爾喚醒超過 n 條線程
notify_all()
喚醒正在等待本條件變量的所有線程。
6. Semaphore Objects
Semaphore 是最古老的同步原語之一,由荷蘭計算機科學家 Edsger W. Dijkstra 發明。(他最早使用名為 P() 和 V() 的函數對應 acquire() 和 release())
Semaphore 在內部管理著一個計數器。調用 acquire() 會使這個計數器 -1,release() 則是 +1.計數器的值永遠不會小于 0,當計數器到 0 時,再調用 acquire() 就會阻塞,直到其他線程來調用 release()
Semaphore 也支持上下文管理協議
class threading.Semaphore(value=1)
本類用于實現 Semaphore 對象。可選參數 value 是計數器的初始值,默認為 1,不可為負,否則引發 ValueError
Python 3.3 起,從一個工廠函數 改變為 類
Semaphore 類包含的方法:
acquire(blocking=True,timeout=None)
本方法用于獲取 Semaphore
當使用默認參數調用本方法時:如果內部計數器的值大于零,將之減一,并返回;如果等于零,則阻塞,并等待其他線程調用 release() 方法以使計數器為正。這個過程有嚴格的互鎖機制控制,以保證如果有多條線程正在等待解鎖,release() 調用只會喚醒其中一條線程。喚醒哪一條是隨機的。本方法返回 True,或無限阻塞
如果 blocking=False,則不阻塞,但若獲取失敗的話,返回 False
當設定了 timeout 參數時,最多阻塞 timeout 秒,如果超時,返回 False
3.2 新增:timeout 參數
release()
釋放 Semaphore,給內部計數器 +1,可以喚醒處于等待狀態的線程
class threading.BoundedSemaphore(value=1)
本類用于實現 bounded semaphore 對象。bounded semaphore 會檢查內部計數器的值,并保證它不會大于初始值,如果超了,就引發一個 ValueError。多數情況下,semaphore 用于守護限制訪問(但不限于 1)的資源,如果 semaphore 被 release() 過多次,這意味著存在 bug
3.3 新增:從工廠函數轉變為類
舉個栗子:
semaphore 常用于守護限制訪問的資源,比如數據庫。實際上在任何對訪問有數量限制的情形下,你都應該使用 bounded semaphore 對象。在創建大量的訪問線程前,你的主線程應該先初始化這個 semaphore。:
max_connection = 5
#...
pool_sema = BoundedSemaphore(value=max_connection)
with pool_sema:
with connectdb():
#...use connection...
7. Event Objects
這是一種最簡單的線程間通信裝置:一個線程操作一個 event,其他線程等待結果
event 對象管理著一個內部 flag,set() 方法可以將之置為 True,clear() 方法則可以將之重置為 False。還有個 wait() 方法會阻塞線程直到 flag 為 True
class threading.Event
本類用于實現 Event 對象。flag 初始值為 False
3.3 新增:從工廠函數改為類
Event 類包含的方法:
is_set()
當且僅當 flag 為 True時,返回True
set()
將 flag 置為 True。所有等待的線程將被喚醒。在 flag 為 True 時調用 wait() 方法的線程不會被阻塞
clear()
將 flag 重置為 False。此后調用 wait() 方法的線程都會被阻塞,直到 flag 被 set() 置為 True
wait(timeout=None)
阻塞線程直到 flag 被置為 True。如果 flag 一開始就是 True,則本方法立即返回。否則,阻塞直到其他線程調用 set() 方法將 flag 置為 True,或超時
當給出 timeout 參數時,它應該是以秒為單位的浮點數
本方法當且僅當 flag 為 True 時返回 True,除非超時,超時返回 False
3.1 以前,本方法始終返回 None
8. Timer Objects
Timer 是 Thread 類的子類,不過本類里內容的執行需要延遲一段時間
Timer 和 Thread 一樣,通過調用 start() 來開始,不過在延遲結束前都可以調用 cancel() 方法來取消。Timer 的延遲時間可能與用戶指定的時間并不完全相同
Timer 使用示例:
defhello():
print('Hello,world')
t = Timer(30.0,hello)
t.start()
class threading.Timer(interval,function,args=None,kwargs=None)
本類用于實現 Timer 對象,Timer 會在 interval 秒后開始執行 function。
3.3 新增:從工廠函數改為類
Timer 類包含的方法:
cancel()
終止計時器并取消內容的執行。本方法只可在計時器走完前調用
9. Barrier Objects
3.2 新增
本類為多條線程需要互相等待對方的狀況提供了一種簡單的同步原語。(注:這里的 barrier 可以想象成賽馬或越野摩托時起點處的柵欄,比賽開始的同時所有選手的柵欄同時打開。)每一條線程調用 wait() 方法后表明自己已就位并進入阻塞狀態,當所有的線程都調用了 wait() 方法時,他們將同時被釋放。
Barrier 對象可以重復使用
下面是一個簡單的栗子:
b = Barrier(2,timeout=5)
defserver():
start_server()
b.wait()
while True:
connection = accept_connection()
process_server_connection(connection)
defclient():
b.wait()
while True:
connection = make_connection()
process_client_connection(connection)
class threading.Barrier(parties,action=None,timeout=None)
創建一個可容納 parties 條線程的 barrier。action 參數是一個在全部線程被釋放時可被其中一條線程調用的可調用對象。timeout 參數是給 wait() 方法準備的,如果線程調用 wait() 方法時沒有顯式設定 timeout,那么這里的 timeout 將作為默認值被使用
Barrier 類包含的方法:
wait(timeout=None)
表示線程就位。如果提供了 timeout 參數,本方法里提供的 timeout 參數優先級較 barrier 類構造器里的高
本方法的返回值是一個 0 到 parties-1 之間的整數,每條線程都不一樣。這個值可以用作挑選一條線程做些清掃工作,比如:
i = barrier.wait()
if i == 0:
#只有一條線程會輸出下面的內容
print('passed the barrier')
如果在類構造器里提供了 action 參數,那么其中一條線程要在被釋放前調用 action。假如 action 引發了異常,barrier 將被置為 broken 狀態
如果調用本方法超時,那么 barrier 將被置為 broken 狀態
如果在有線程已經在等待時,barrier 被置為 broken狀態,或調用了 reset() 方法,那么將引發一個 BrokenBarrierError 異常
reset()
本方法將 barrier 置為初始狀態,即 empty 狀態。所有已經在等待的線程都會接收到 BrokenBarrierError 異常
注意當有其他處于 unknown 狀態的線程時,調用此方法將可能獲取到額外的訪問。因此如果一個 barrier 進入了 broken 狀態,最好是放棄他并新建一個 barrier,而不是調用本方法
abort()
將 barrier 置為 broken 狀態。本方法將使所有正在等待或將要調用 wait() 方法的線程收到 BrokenBarrierError 異常。本方法的使用情景為,比如有一條線程需要 abort(),又不想給其他線程造成死鎖的狀態
或許設定 timeout 參數要比使用本方法更可靠
parites
將要使用本 barrier 的線程的數量
n_waiting
正在等待本 barrier 的線程的數量
broken
布爾值。如果本 barrier 為 broken 狀態,則為 True
exception threading.BrokenBarrierError
本異常是 RuntimeError 的子類。當 barrier 被 reset() 或 broken 時引發
10. 在 with 語句 中使用 locks、condition 和 semaphore
本模塊里的對象,只要有 acquire() 、release() 這對方法的,都支持上下文管理協議。其中 acquire() 會在 __enter__() 里調用,release() 會在 __quit__() 里調用。因此,下面的用法:
with some_lock:
#do sth.
等價于:
some_lock.acquire()
try:
#do_sth.
finally:
some_lock.release()
總結
以上是生活随笔為你收集整理的python多线程模块_python 多线程模块参考的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信服务项目表
- 下一篇: 防止SQL注入的五种方法