Python 對自由執行緒的支援¶
從 3.13 版本開始,CPython 支援一個名為自由執行緒的 Python 構建,其中全域性直譯器鎖 (GIL) 已停用。自由執行緒執行允許透過在可用 CPU 核心上並行執行執行緒來充分利用可用的處理能力。雖然並非所有軟體都會自動受益,但針對多執行緒設計的程式將在多核硬體上執行得更快。
自由執行緒模式正在執行並持續改進,但與常規構建相比,單執行緒工作負載會增加一些開銷。此外,第三方包,特別是那些帶有擴充套件模組的包,可能尚未準備好在自由執行緒構建中使用,並將重新啟用GIL。
本文件描述了自由執行緒對 Python 程式碼的影響。有關如何編寫支援自由執行緒構建的 C 擴充套件的資訊,請參閱C API 擴充套件對自由執行緒的支援。
參見
PEP 703 – 使 CPython 中的全域性直譯器鎖成為可選,以獲取自由執行緒 Python 的整體描述。
安裝¶
從 Python 3.13 開始,官方 macOS 和 Windows 安裝程式可選支援安裝自由執行緒 Python 二進位制檔案。安裝程式可在https://python.club.tw/downloads/獲取。
有關其他平臺的資訊,請參閱安裝自由執行緒 Python,這是一個社群維護的安裝指南,用於安裝自由執行緒 Python。
從原始碼構建 CPython 時,應使用--disable-gil
配置選項來構建自由執行緒 Python 直譯器。
識別自由執行緒 Python¶
要檢查當前直譯器是否支援自由執行緒,python -VV
和sys.version
包含“free-threading build”。新的sys._is_gil_enabled()
函式可用於檢查 GIL 是否在正在執行的程序中實際停用。
配置變數sysconfig.get_config_var("Py_GIL_DISABLED")
可用於確定構建是否支援自由執行緒。如果變數設定為1
,則構建支援自由執行緒。這是與構建配置相關的決策的推薦機制。
自由執行緒 Python 中的全域性直譯器鎖¶
CPython 的自由執行緒構建支援使用環境變數PYTHON_GIL
或命令列選項-X gil
在執行時可選地啟用 GIL。
當匯入未明確標記為支援自由執行緒的 C-API 擴充套件模組時,GIL 也可能會自動啟用。在這種情況下將列印警告。
除了各個包的文件之外,以下網站跟蹤了流行包對自由執行緒支援的狀態
執行緒安全¶
CPython 的自由執行緒構建旨在在 Python 級別提供與預設 GIL 啟用構建類似的執行緒安全行為。諸如dict
、list
和set
等內建型別使用內部鎖來防止併發修改,其行為類似於 GIL。然而,Python 歷來並未保證對這些內建型別進行併發修改的特定行為,因此這應被視為對當前實現的描述,而不是對當前或未來行為的保證。
備註
在可能的情況下,建議使用threading.Lock
或其他同步原語,而不是依賴內建型別的內部鎖。
已知限制¶
本節描述了自由執行緒 CPython 構建的已知限制。
不朽化¶
3.13 版本的自由執行緒構建使某些物件不朽。不朽物件不會被釋放,並且其引用計數永遠不會被修改。這樣做是為了避免引用計數爭用,這會阻礙高效的多執行緒擴充套件。
當主執行緒執行後第一次啟動新執行緒時,物件將變為不朽。以下物件被不朽化
由於不朽物件永遠不會被釋放,因此建立許多這些型別物件的應用程式可能會看到記憶體使用量增加。預計這將在 3.14 版本中得到解決。
此外,程式碼中的數字和字串文字以及sys.intern()
返回的字串也已不朽化。此行為預計將保留在 3.14 自由執行緒構建中。
幀物件¶
從其他執行緒訪問幀物件是不安全的,這樣做可能會導致程式崩潰。這意味著sys._current_frames()
在自由執行緒構建中通常不安全使用。諸如inspect.currentframe()
和sys._getframe()
等函式通常是安全的,只要生成的幀物件不傳遞給另一個執行緒。
迭代器¶
在多個執行緒之間共享相同的迭代器物件通常是不安全的,執行緒在迭代時可能會看到重複或丟失的元素,或導致直譯器崩潰。
單執行緒效能¶
與預設的 GIL 啟用構建相比,自由執行緒構建在執行 Python 程式碼時具有額外的開銷。在 3.13 中,pyperformance 套件上的開銷約為 40%。將大部分時間花在 C 擴充套件或 I/O 上的程式受到的影響會較小。最大的影響是由於專門化的自適應直譯器 (PEP 659) 在自由執行緒構建中被停用。我們預計將在 3.14 版本中以執行緒安全的方式重新啟用它。預計此開銷將在即將釋出的 Python 版本中減少。我們的目標是 pyperformance 套件上的開銷與預設的 GIL 啟用構建相比為 10% 或更少。
行為變化¶
本節描述了自由執行緒構建中 CPython 的行為變化。
上下文變數¶
在自由執行緒構建中,標誌thread_inherit_context
預設設定為 true,這使得使用threading.Thread
建立的執行緒以呼叫start()
的呼叫者的Context()
副本啟動。在預設的 GIL 啟用構建中,該標誌預設為 false,因此執行緒以空的Context()
啟動。
警告過濾器¶
在自由執行緒構建中,標誌context_aware_warnings
預設設定為 true。在預設的 GIL 啟用構建中,該標誌預設為 false。如果標誌為 true,則warnings.catch_warnings
上下文管理器使用上下文變數進行警告過濾。如果標誌為 false,則catch_warnings
修改全域性過濾器列表,這並非執行緒安全。有關更多詳細資訊,請參閱warnings
模組。