_thread --- 低階執行緒 API


這個模組提供了與多個執行緒(也稱為:dfn:輕量級行程 或 :dfn: 任務)一起工作的低階原始物件 --- 多個控制執行緒分享其全域資料空間。為了處理同步問題,也提供了簡單的鎖 (lock) 機制(也稱為:dfn:互斥鎖二進位號誌)。 threading 模組提供了一個建立在這個模組之上的更易於使用和高階的執行緒 API。

在 3.7 版的變更: 這個模組之前是可選擇性的,但現在已經是可用的。

這個模組定義了以下的常數和函式:

exception _thread.error

在執行緒相關的錯誤發生時引發。

在 3.3 版的變更: 現在是內建例外 RuntimeError 的別名。

_thread.LockType

這是鎖物件的型別。

_thread.start_new_thread(function, args[, kwargs])

開始一個新的執行緒並回傳其識別字 (identifier) 。該執行緒執行帶有引數列表 args*(必須是一個 tuple(元組))的函式 *function。可選的 kwargs 引數指定一個關鍵字引數的字典。

當函式回傳時,執行緒會靜默退出。

當函式因未處理的例外終止時,將呼叫 sys.unraisablehook() 來處理該例外。鉤子引數的 object 屬性是 function。預設情況下,會列印堆疊跟蹤,然後執行緒退出(但其他執行緒會繼續運行)。

當函式引發 SystemExit 例外時,它會被靜默忽略。

引發一個 稽核事件 _thread.start_new_thread,帶有引數 functionargskwargs

在 3.8 版的變更: 現在使用 sys.unraisablehook() 來處理未處理的例外。

_thread.interrupt_main(signum=signal.SIGINT, /)

模擬一個訊號到達主執行緒的效果。執行緒可以使用此函式來中斷主執行緒,但無法保證中斷會立即發生。

如果提供了 signum,則模擬指定的訊號編號。如果未提供 signum,則模擬 signal.SIGINT 訊號。

如果給定的訊號在 Python 中未被處理(即設置為 signal.SIG_DFLsignal.SIG_IGN),此函式不做任何操作。

在 3.10 版的變更: 新增了 signum 引數以自定義訊號編號。

備註

這並不會發出對應的訊號,而是安排呼叫相應的處理器(如果存在的話)。如果您想真正發出訊號,請使用 signal.raise_signal()

_thread.exit()

引發 SystemExit 例外。當未捕獲時,將導致執行緒靜默退出。

_thread.allocate_lock()

回傳一個新的鎖物件。鎖物件的方法如下所述。初始狀況下鎖是解鎖狀態。

_thread.get_ident()

回傳當前執行緒的「執行緒識別字」。這是一個非零的整數。它的值沒有直接的含義;它被用作一個 magic cookie,例如用於索引特定於執行緒的資料的字典。當執行緒退出並建立另一個執行緒時,執行緒識別字可能會被重複使用。

_thread.get_native_id()

回傳由核心 (kernel) 分配的當前執行緒的原生整數執行緒 ID。這是一個非負整數。它的值可用於在整個系統中唯一標識此特定執行緒(直到執行緒終止後,該值可能被操作系統重新使用)。

適用:Windows、FreeBSD、Linux、macOS、OpenBSD、NetBSD、AIX、DragonFlyBSD。

在 3.8 版被加入.

_thread.stack_size([size])

回傳在建立新執行緒時使用的執行緒堆疊大小。可選的 size 引數指定了隨後建立的執行緒要使用的堆疊大小,必須是 0(使用平台或配置的預設值)或至少 32,768(32 KiB)的正整數值。如果未指定 size,則使用 0。如果不支持更改執行緒堆疊大小,則會引發 RuntimeError 錯誤。如果指定的堆疊大小無效,則會引發 ValueError 錯誤,並且堆疊大小不會被修改。目前,32 KiB 是保證解譯器本身具有足夠堆疊空間所支持的最小堆疊大小值。請注意,某些平台對於堆疊大小的值可能有特定的限制,例如要求最小堆疊大小 > 32 KiB,或要求按系統記憶體頁面大小的倍數進行分配。應參考平台文檔以獲取更多訊息(4 KiB 頁面是比較普遍的;在缺乏更具體訊息的情況下,建議使用 4096 的倍數作為堆疊大小)。

適用:Windows, pthreads。

Unix 平台上支援 POSIX 執行緒。

_thread.TIMEOUT_MAX

Lock.acquiretimeout 參數所允許的最大值。指定超過此值的 timeout 將引發 OverflowError 錯誤。

在 3.2 版被加入.

鎖物件具有以下方法:

lock.acquire(blocking=True, timeout=-1)

沒有任何可選引數時,此方法無條件地獲取鎖,必要時會等待直到被另一個執行緒釋放(一次只能有一個執行緒獲取鎖 --- 這正是鎖存在的原因)。

如果存在 blocking 引數,則根據其值執行操作:如果為 False,只有在可以立即獲取鎖而無需等待的情況下才獲取鎖,而如果為 True,則像上面一樣無條件地獲取鎖。

如果存在浮點數的 timeout 引數且為正值,則它指定了在回傳之前的最大等待時間(以秒為單位)。如果 timeout 引數為負值,則表示等待時間會無限期地等待。如果 blocking 為 False,則你無法指定 timeout

如果成功獲取鎖,回傳值為 True,否則為 False

在 3.2 版的變更: 新增的 timeout 參數。

在 3.2 版的變更: 現在獲取鎖的操作可以被 POSIX 訊號中斷。

lock.release()

釋放鎖。鎖必須先前被獲取,但不一定是由同一個執行緒獲取的。

lock.locked()

回傳鎖的狀態:如果鎖已被某個執行緒獲取,則回傳 True,否則回傳 False

除了這些方法之外,鎖物件還可以透過 with 語句來使用,例如:

import _thread

a_lock = _thread.allocate_lock()

with a_lock:
    print("a_lock is locked while this executes")

注意事項:

  • 執行緒與中斷的互動可能會有奇怪的情況:任何一個執行緒都有可能收到 KeyboardInterrupt 例外。(當 signal 模組可用時,中斷總是會進入主執行緒。)

  • 呼叫 sys.exit() 函數或引發 SystemExit 例外等同於呼叫 _thread.exit() 函式。

  • 無法在鎖的 acquire() 方法上中斷執行, KeyboardInterrupt 例外會在鎖被獲取後發生。

  • 當主執行緒退出時,其他執行緒是否保留是由系統決定的。在大多數系統上,它們將被終止,而不會執行 try ... finally 子句或執行物件的解構函式。

  • 當主執行緒退出時,它不會執行任何通常的清理操作(除非有 try ... finally 子句),並且標準 I/O 檔案不會被刷新。