轉自:https://blog.csdn.net/weixin_41594007/article/details/79485847
Python GIL
并行:多個CPU同時執行多個任務,就好像有兩個程序,這兩個程序是真的在兩個不同的CPU內同時被執行。
并發:CPU交替處理多個任務,還是有兩個程序,但是只有一個CPU,會交替處理這兩個程序,而不是同時執行,只不過因為CPU執行的速度過快,而會使得人們感到是在“同時”執行,執行的先后取決于各個程序對于時間片資源的爭奪。大家可以參考下圖的實物圖就行理解:
并行和并發同屬于多任務,目的是要提高CPU的使用效率。這里需要注意的是,一個CPU永遠不可能實現并行,即一個CPU不能同時運行多個程序,但是可以在隨機分配的時間片內交替執行(并發),就好像一個人不能同時看兩本書,但是卻能夠先看第一本書半分鐘,再看第二本書半分鐘,這樣來回切換。
接下來我們來看看進程和線程之間的區別:
兩個多線程同時執行死循環,查看單個CPU的使用率:
兩個多線程同時執行死循環,查看兩個CPU的使用率:
兩個多進程同時執行死循環,查看兩個CPU使用率:
也就是說,多線程并不會充分調用兩個CPU,而是會像在一個CPU上充分運轉,而多進程則是會完全調用兩個CPU,同時執行;
Guido van Rossum(吉多·范羅蘇姆)創建python時就只考慮到單核cpu,解決多線程之間數據完整性和狀態同步的最簡單方法自然就是加鎖, 于是有了GIL這把超級大鎖。因為cpython解析只允許擁有GIL全局解析器鎖才能運行程序,這樣就保證了保證同一個時刻只允許一個線程可以使用cpu。由于大量的程序開發者接收了這套機制,現在代碼量越來越多,已經不容易通過c代碼去解決這個問題。
什么是GIL?
即全局解釋器所(global interpreter lock),每個線程在執行時候都需要先獲取GIL,保證同一時刻只有一個線程可以執行代碼,即同一時刻只有一個線程使用CPU,也就是說多線程并不是真正意義上的同時執行。
那么,我們改如何解決GIL鎖的問題呢?
1.更換cpython為jpython(不建議)
2.使用多進程完成多線程的任務
3.在使用多線程可以使用c語言去實現
以下是幾個面試會遇到的問題,希望對大家有所幫助:
問題1: 什么時候會釋放Gil鎖,
答 :??
1 遇到像 i/o操作這種 會有時間空閑情況 造成cpu閑置的情況會釋放Gil
2 會有一個專門ticks進行計數 一旦ticks數值達到100 這個時候釋放Gil鎖 線程之間開始競爭Gil鎖(說明:
? ? ticks這個數值可以進行設置來延長或者縮減獲得Gil鎖的線程使用cpu的時間)
問題2: 互斥鎖和Gil鎖的關系
Gil鎖? : 保證同一時刻只有一個線程能使用到cpu
互斥鎖 : 多線程時,保證修改共享數據時有序的修改,不會產生數據修改混亂
首先假設只有一個進程,這個進程中有兩個線程 Thread1,Thread2, 要修改共享的數據date, 并且有互斥鎖
執行以下步驟
(1)多線程運行,假設Thread1獲得GIL可以使用cpu,這時Thread1獲得 互斥鎖lock,Thread1可以改date數據(但并
沒有開始修改數據)
(2)Thread1線程在修改date數據前發生了 i/o操作 或者 ticks計數滿100 (注意就是沒有運行到修改data數據),這個
時候 Thread1 讓出了Gil,Gil鎖可以被競爭
(3) Thread1 和 Thread2 開始競爭 Gil (注意:如果Thread1是因為 i/o 阻塞 讓出的Gil Thread2必定拿到Gil,如果
Thread1是因為ticks計數滿100讓出Gil 這個時候 Thread1 和 Thread2 公平競爭)
(4)假設 Thread2正好獲得了GIL, 運行代碼去修改共享數據date,由于Thread1有互斥鎖lock,所以Thread2無法更改共享數據
date,這時Thread2讓出Gil鎖 , GIL鎖再次發生競爭?
(5)假設Thread1又搶到GIL,由于其有互斥鎖Lock所以其可以繼續修改共享數據data,當Thread1修改完數據釋放互斥鎖lock,
Thread2在獲得GIL與lock后才可對data進行修改
以上描述了 互斥鎖和Gil鎖的 一個關系