目錄
Python的GIL(Global Intercepto Lock)
重點提前:
那python的多線程是不是不存在? :多線程是存在的。
那到底我們還能使用多線程不呢? :可以使用。
- I/O操作比較密集時,可以適當的 使用多線程,充分利用CPU的性能。因爲當執行 I/O 操作時,CPU會處於空閒的狀態,這是就可以切換到其他線程,更好的利用 CPU 工作。
Python的GIL(Global Intercepto Lock)
- 全局解釋器鎖致使python 多線程任務不能利用多核的 元兇,
全局解釋器鎖GIL設計理念與限制
- GIL的設計簡化了CPython的實現,使得對象模型,包括關鍵的內建類型如字典,都是隱含可以併發訪問的。鎖住全局解釋器使得比較容易的實現對多線程的支持,但也損失了多處理器主機的並行計算能力。
- 同一進程中假如有多個線程運行,一個線程在運行python程序的時候會霸佔python解釋器(加了一把鎖即GIL),使該進程內的其他線程無法運行,等該線程運行完後其他線程才能運行。如果線程運行過程中遇到耗時操作,則解釋器鎖解開,使其他線程運行。所以在多線程中,線程的運行仍是有先後順序的,並不是同時進行。
- 在做I/O操作時,GIL總是會被釋放。對所有面向I/O 的(會調用內建的操作系統C 代碼的)程序來說,GIL 會在這個I/O 調用之前被釋放,以允許其它的線程在這個線程等待I/O 的時候運行。如果是純計算的程序,沒有 I/O 操作,解釋器會每隔 100 次操作就釋放這把鎖,讓別的線程有機會執行(這個次數可以通過 sys.setcheckinterval 來調整)如果某線程並未使用很多I/O 操作,它會在自己的時間片內一直佔用處理器(和GIL)。也就是說,I/O 密集型的Python 程序比計算密集型的程序更能充分利用多線程環境的好處。
計算密集型任務(CPU-bound) 的特點是要進行大量的計算,佔據着主要的任務,消耗CPU資源,一直處於滿負荷狀態。比如複雜的加減乘除、計算圓周率、對視頻進行高清解碼等等,全靠CPU的運算能力。這種計算密集型任務雖然也可以用多任務完成,但是任務越多,花在任務切換的時間就越多,CPU執行任務的效率就越低,所以,要最高效地利用CPU,計算密集型任務同時進行的數量應當等於CPU的核心數。
計算密集型任務由於主要消耗CPU資源,因此,代碼運行效率至關重要。Python這樣的腳本語言運行效率很低,完全不適合計算密集型任務。對於計算密集型任務,最好用C語言編寫。
IO密集型任務(I/O bound)的特點是指磁盤IO、網絡IO佔主要的任務,CPU消耗很少,任務的大部分時間都在等待IO操作完成(因爲IO的速度遠遠低於CPU和內存的速度)。
IO密集型任務執行期間,99%的時間都花在IO上,花在CPU上的時間很少,因此,用運行速度極快的C語言替換用Python這樣運行速度極低的腳本語言,完全無法提升運行效率。
對於IO密集型任務,任務越多,CPU效率越高,但也有一個限度。常見的大部分任務都是IO密集型任務,比如請求網頁、讀寫文件等。
對於IO密集型任務,最合適的語言就是開發效率最高(代碼量最少)的語言,腳本語言是首選,C語言最差。
GIL運行流程:
在多線程環境中,Python 虛擬機按以下方式執行:
- 1. 設置GIL
- 2. 切換到一個線程去運行
- 3. 運行:
- a. 指定數量的字節碼指令,或者
- b. 線程主動讓出控制(可以調用time.sleep(0))
- 4. 把線程設置爲睡眠狀態
- 5. 解鎖GIL
- 6. 再次重複以上所有步驟
。
GIL解決方法
- 使用多線程,多進程中因爲每個進程都能被系統分配資源,相當於每個進程有了一個python解釋器,所以多進程可以實現多個進程的同時運行,缺點是進程系統資源開銷大
自己結合網上的資料,和自己所學總結,如有不對,望請指教。