Python的全域性鎖

2021-10-10 18:15:46 字數 1997 閱讀 6903

gil (global interperter lock) 稱作全域性直譯器鎖,也可以稱它為全域性排他鎖。gil只在cpython中存在。比如jpython就沒有這個概念。

在python多執行緒的情況下,每個執行緒的執行方式是這樣的

獲取gil -> 執行**,直到遇到io操作,執行了一定的**量(python2),執行了一定的時間(python3) -> 釋放gil

那麼問題來了,gil是全域性鎖,也就是乙個程序中只有乙個,沒有拿到gil就不允許在cpu中執行,所以python多執行緒在並不能充分利用多核cpu。

cpu密集型任務的主要特點就是需要進行大量的計算,消耗cpu資源。cpu密集型程式雖然可以採用多工來完成,但任務數越多花在任務切換的時間也就越多,所以要高效的利用cpu,cpu密集型任務的數量在理想的情況下應該等於cpu核心數+1。

多工可以使用多程序和多執行緒來實現,在多程序情況下,程序數應該等於cpu核心數+1,多執行緒情況下,執行緒數也應該等於cpu核心數+1。python在多程序下沒有什麼問題,但是在多執行緒下問題就出來了。

由於python的gil的存在,乙個程序中只能有乙個執行緒在執行,無法充分利用多核cpu。所以python的多執行緒在處理cpu密集型任務時並不是很友好,解決的辦法就是使用多程序+協程的方式。

io密集型任務的主要特點就是大量涉及到網路、磁碟io的任務。這類任務對cpu的消耗很低,任務的大部分時間都在等待io操作完成,對於io密集型任務,任務數越多,cpu的效率就越高,但是也有乙個限度。比較理想的任務數是cpu核心數/(1-阻塞係數),阻塞係數一般在0.8-0.9,所以任務數應為核心數的5倍或10倍。

python的執行緒會在遇到io操作時釋放gil,執行別的執行緒, 所以python多執行緒對io密集型任務比較友好。

python雖然是有gil,但並不一定就是執行緒安全的。python在兩種情況下會釋放執行緒鎖,第一種,該執行緒在進入io操作之前,會主動釋放gil;第二種,直譯器不間斷的執行了1000位元組碼(python2)或執行15ms後(python3)後也會釋放gil。所以乙個執行緒會隨時釋放gil,那麼它就不是執行緒安全的。

先看第一種情況,假設執行緒a進入了io操作時釋放了執行緒鎖,由於a的io操作等待時間不確定,所以執行緒b一定會得到gil,這種情況下是執行緒安全的。

第二種情況,執行緒a在不間斷的執行了1000位元組碼(python2)或執行15ms後(python3)後釋放了gil,這個時候執行緒a會和執行緒b同時競爭gil,python3會提高b的優先順序,但是也並不是說b一定會得到gil。在這種情況下釋放gil,會出現執行緒安全問題。

這個首先要看一下python執行程式的方式,python在執行乙個程式之前,會先將程式轉換為位元組碼,然後直譯器會去執行位元組碼。

是否執行緒安全就會取決於釋放gil前的操作是否是乙個原子性的操作,或者說,釋放gil之前是否將一條python語句執行完了。

舉個例子

import dis

n =0

defadd()

:global n

n = n +

1return n

if __name__ ==

'__main__'

: dis.dis(add)

執行這段**會輸出以下資訊

9           0 load_global              0 (n)

2 load_const 1 (1)

4 binary_add

6 store_global 0 (n)

10 8 load_global 0 (n)

10 return_value

可以看到,n = n + 1這條語句,會被翻譯成4條位元組碼,所以加法這個操作並不是原子性的。如果在釋放gil的時候,剛好執行到了4 binary_add這裡,還未將計算後的值賦值給n,那麼在另外乙個執行緒中執行的加法操作就會被這次的操作覆蓋掉。這就是執行緒不安全的情況。

Python的GIL全域性直譯器鎖

概念保證同一時間僅有乙個執行緒對資源有操作許可權 在乙個程序內,同一時刻只能有乙個執行緒執行 python多執行緒中gil鎖只是在cpu操作時 如 計算 才是序列的,其他都是並行的,所以比序列快很多 為什麼會有gil 為了利用多核,python開始支援多執行緒。而解決多執行緒之間資料完整性和狀態同步...

表鎖和全域性鎖

目錄 鎖的作用 處理併發問題 鎖的分類 全域性鎖表級鎖 行鎖 命令 flush tables with read lock ftwrl 這個庫處理唯讀狀態 全庫邏輯備份問題 1 主庫備份,業務停擺 2 從庫備份,不能執行binlog,導致主從延遲 在不支援事物的引擎下可以使用 有事務機制的備份 my...

python全域性直譯器鎖 GIL 的問題

gil即全域性直譯器鎖,是屬於直譯器層面的互斥鎖,確切的說是cpython直譯器內部的一把鎖。gil是為了鎖定整個直譯器內部的全域性資源,每個執行緒想要執行首先獲取gil,而gil本身又是一把互斥鎖,造成所有執行緒只能乙個乙個併發交替的執行。注意多個python程序 多個gil鎖 gil產生的背景 ...