GIL(全局解釋器鎖)
引入
現在絕大部分的Python都是CPython解釋器(但不是必須使用CPython解釋器),而CPython的一個特性就是有GIL,作用保證解釋器級別的代碼在運行時不被其他的線程進行修改,即加鎖處理。
造成的影響是:在同一個時刻內一個進程內的多個線程只能有一個線程被運行。但是要註意:GIL不是Python的特性,而是Python所使用的解釋器的特性。
詳細介紹:
GIL的本質就是一把互斥鎖,既然是互斥鎖,它們的本質都是將並發運行變成串行運行,使在同一時刻內,共享數據只能被一個進行內的一個任務(線程)修改,從而保證數據的安全。
可以肯定的是,保證不同級別的數據的安全,就應該加不同的鎖。
在CPython中有兩種級別的數據:
解釋器級別數據:解釋器代碼和線程傳入的代碼所構成的數據集。
用戶自定義數據:用戶在程序中自定義的數據集。
所有線程的任務,都需要將任務的代碼當做參數傳給解釋器的代碼去執行,即所有的線程要想運行自己的任務,首先需要解決的是能夠訪問到解釋器的代碼,而解釋器代碼是所有線程的共享數據,也就是說任何的線程都可以訪問到解釋器代碼,但是能訪問到不代表可以獲取解釋器代碼的執行權限。因此,線程在運行時,首先要做的就是獲取解釋器的執行權限。總有一個線程先得到解釋器的執行權限,那麽其它的線程就要處於等待狀態。線程在獲取到執行權限後,首先為解釋器級別數據(解釋器代碼+線程代碼)進行加鎖,該鎖便是GIL鎖,防止其他的線程在該線程沒有解鎖之前對解釋器的使用,只有在該線程釋放掉解釋器的執行權限之後,其他的線程才能進行爭奪。
GIL的作用對象是所有的線程(同一進程的線程+非同一進程的線程),這把鎖保證的只是解釋器級別數據的安全性,但是不能保證用戶數據級別的數據的安全性,解決這一問題,需要的就是另一把鎖:互斥鎖。互斥鎖針對的是同一進程之間的共享數據,再某一線程對其修改時,不能被其它的線程修改,保證了數據的安全性。
GIL的出現對程序采用多線程或多進程的影響:
結果:
計算型---------------------------->多核--------------------------------->采用多進程
IO型------------------------------->多核--------------------------------->采用多線程
GIL(全局解釋器鎖)