python 多執行緒為什麼雞肋?
什麼是全域性直譯器鎖GIL
Python程式碼的執行由Python 虛擬機器(也叫直譯器主迴圈,CPython版本)來控制,Python 在設計之初就考慮到要在直譯器的主迴圈中,同時只有一個執行緒在執行,即在任意時刻,只有一個執行緒在直譯器中執行。對Python 虛擬機器的訪問由全域性直譯器鎖(GIL)來控制,正是這個鎖能保證同一時刻只有一個執行緒在執行。
在多執行緒環境中,Python 虛擬機器按以下方式執行:
1. 設定GIL
2. 切換到一個執行緒去執行
3. 執行:
a. 指定數量的位元組碼指令,或者
2. 切換到一個執行緒去執行
3. 執行:
a. 指定數量的位元組碼指令,或者
b. 執行緒主動讓出控制(可以呼叫time.sleep(0))
4. 把執行緒設定為睡眠狀態
5. 解鎖GIL
6. 再次重複以上所有步驟
4. 把執行緒設定為睡眠狀態
5. 解鎖GIL
6. 再次重複以上所有步驟
在呼叫外部程式碼(如C/C++擴充套件函式)的時候,GIL 將會被鎖定,直到這個函式結束為止(由於在這期間沒有Python 的位元組碼被執行,所以不會做執行緒切換)。
全域性直譯器鎖GIL設計理念與限制
GIL的設計簡化了CPython的實現,使得物件模型,包括關鍵的內建型別如字典,都是隱含可以併發訪問的。鎖住全域性直譯器使得比較容易的實現對多執行緒的支援,但也損失了多處理器主機的平行計算能力。
但是,不論標準的,還是第三方的擴充套件模組,都被設計成在進行密集計算任務是,釋放GIL。
還有,就是在做I/O操作時,GIL總是會被釋放。對所有面向I/O 的(會呼叫內建的作業系統C 程式碼的)程式來說,GIL 會在這個I/O 呼叫之前被釋放,以允許其它的執行緒在這個執行緒等待I/O 的時候執行。如果是純計算的程式,沒有 I/O 操作,直譯器會每隔 100 次操作就釋放這把鎖,讓別的執行緒有機會執行(這個次數可以通過 sys.setcheckinterval 來調整)如果某執行緒並未使用很多I/O 操作,它會在自己的時間片內一直佔用處理器(和GIL)。也就是說,I/O 密集型的Python 程式比計算密集型的程式更能充分利用多執行緒環境的好處。
下面是Python 2.7.9手冊中對GIL的簡單介紹:
The mechanism used by the CPython interpreter to assure that only one thread executes Python bytecode at a time. This simplifies the CPython implementation by making the object model (including critical built-in types such as dict) implicitly safe against
concurrent access. Locking the entire interpreter makes it easier for the interpreter to be multi-threaded, at the expense of much of the parallelism afforded by multi-processor machines.
However, some extension modules, either standard or third-party, are designed so as to release the GIL when doing computationally-intensive tasks such as compression or hashing. Also, the GIL is always released when doing I/O.
Past efforts to create a “free-threaded” interpreter (one which locks shared data at a much finer granularity) have not been successful because performance suffered in the common single-processor case. It is believed that overcoming this performance issue would make the implementation much more complicated and therefore costlier to maintain.
從上文中可以看到,針對GIL的問題做的很多改進,如使用更細粒度的鎖機制,在單處理器環境下反而導致了效能的下降。普遍認為,克服這個效能問題會導致CPython實現更加複雜,因此維護成本更加高昂。
However, some extension modules, either standard or third-party, are designed so as to release the GIL when doing computationally-intensive tasks such as compression or hashing. Also, the GIL is always released when doing I/O.
Past efforts to create a “free-threaded” interpreter (one which locks shared data at a much finer granularity) have not been successful because performance suffered in the common single-processor case. It is believed that overcoming this performance issue would make the implementation much more complicated and therefore costlier to maintain.
從上文中可以看到,針對GIL的問題做的很多改進,如使用更細粒度的鎖機制,在單處理器環境下反而導致了效能的下降。普遍認為,克服這個效能問題會導致CPython實現更加複雜,因此維護成本更加高昂。
相關文章
- 為什麼有人說 Python 多執行緒是雞肋?Python執行緒
- Python多執行緒雞年不雞肋Python執行緒
- 什麼是多執行緒?Python多執行緒有什麼優勢?執行緒Python
- redis為什麼用單執行緒不用多執行緒Redis執行緒
- python為什麼要用執行緒Python執行緒
- Oracle OMF 為雞肋Oracle
- Python多執行緒是什麼意思?有什麼優勢?Python執行緒
- 為什麼多執行緒可以利用到多核?執行緒
- 什麼是Python執行緒?Python執行緒如何建立?Python執行緒
- 執行緒池管理(1)-為什麼需要執行緒池執行緒
- 為什麼要使用執行緒池執行緒
- 【多執行緒與高併發】Java守護執行緒是什麼?什麼是Java的守護執行緒?執行緒Java
- python多執行緒Python執行緒
- Python 多執行緒Python執行緒
- Python 多執行緒多程式Python執行緒
- 24. 一個普通main方法的執行,是單執行緒模式還是多執行緒模式?為什麼?AI執行緒模式
- 程式執行緒新解:什麼是程式?什麼是執行緒?執行緒
- ArrayList 為什麼執行緒不安全執行緒
- 防止OA系統成為雞肋
- 王者榮耀多執行緒模式怎麼開啟? 王者榮耀多執行緒模式是什麼執行緒模式
- 為什麼redis是單執行緒的以及為什麼這麼快?Redis執行緒
- python多執行緒示例Python執行緒
- Python的GIL是什麼鬼,多執行緒效能究竟如何Python執行緒
- 為什麼多執行緒讀寫shared_ptr需要加鎖執行緒
- python多執行緒中:如何關閉執行緒?Python執行緒
- Python——程式、執行緒、協程、多程式、多執行緒(個人向)Python執行緒
- 【Python】 多程式與多執行緒Python執行緒
- python多執行緒程式設計1— python對多執行緒的支援Python執行緒程式設計
- 我會手動建立執行緒,為什麼讓我使用執行緒池?執行緒
- Redis單執行緒,為什麼速度快Redis執行緒
- 多執行緒和多執行緒同步執行緒
- Redis為什麼是單執行緒?為什麼有如此高的效能?Redis執行緒
- 為什麼?為什麼StringBuilder是執行緒不安全的?UI執行緒
- python 多執行緒就這麼簡單(續)Python執行緒
- redis是單執行緒的,為什麼這麼快Redis執行緒
- 多執行緒【執行緒池】執行緒
- 多執行緒--執行緒管理執行緒
- Java多執行緒——執行緒Java執行緒