天天看點

python多線程gil_Python多線程補充—GIL

GIL(Global Interpreter Lock )

GIL從名稱翻譯:全局解釋器鎖。

作用:限制同一個程序内隻同一時刻允許一個線程執行(不允許并行),即使計算機有多核功能。進而保證線程安全

來源:Cpython解釋器

也就是說GIL是一把互斥鎖,限制程式并行執行。它的級别是解釋器級别的,強制的,不是Python的特性,而是Cpython解釋器特有的。

為什麼會有GIL呢,查過一些資料,我的了解是從python垃圾回收機制說起

垃圾回收機制

Python中的垃圾回收是以引用計數為主,分代收集為輔。

在Python中,如果一個對象的引用數為0,Python虛拟機就會回收這個對象的記憶體。

導緻引用計數+1的情況對象被建立,例如a=23

對象被引用,例如b=a

對象被作為參數,傳入到一個函數中,例如func(a)

對象作為一個元素,存儲在容器中,例如list1=[a,a]

導緻引用計數-1的情況對象的别名被顯式銷毀,例如del a

對象的别名被賦予新的對象,例如a=24

一個對象離開它的作用域,例如f函數執行完畢時,func函數中的局部變量(全局變量不會)

對象所在的容器被銷毀,或從容器中删除對象

如果,一個變量同時被引用呢,在同一個程序内,各個線程可以共享資料。當他們同時引用一個對象,則會使垃圾回收機制的計數錯誤,可能使對象還有引用,但是卻被回收了。是以Cpython解釋器就引入了GIL鎖

在一個程序内,每個線程想要擷取cpu運作的權限,都要擷取GIL鎖對象,是以線程們無法并行執行。也就避免了上述問題。

而擷取GIL的線程,無論何時,它一旦睡眠或者是等待I/O,它沒有了運作PYthon代碼的必要,它就會讓出GIL,其他線程就會有擷取GIL的機會。這也叫做協同式多任務管理

既然有了GIL,為什麼還需要自己給資料加上鎖(Lock)呢?

因為除了協同式多任務管理,還有搶占式多任務管理,也就是說一個線程在執行Python代碼時,有可能會被強制讓出GIL,讓其他線程執行。

而且在資料處理的過程中也能會有I/O阻塞,使線程主動讓出GIL,其他線程可能擷取GIL處理同一個資料,造成資料混亂

是以,GIL保護的是解釋器級别的資料,我們自己建立的資料需要我們自己加鎖。

總結:

GIL的優點就是保護線程安全,缺點也很明顯:無法利用多核優勢,使程式運作速度變慢,而現在計算機多核是十分普遍,似乎GIL的缺陷也顯得更加的明顯,但是Pyhton中很多庫都是預設有GIL存在的,而且上述也提到,遇到I/O阻塞會切換,無論多核單核,也無法改變阻塞的時間。是以GIL對于 I/O密集型的任務,影響不大。對于計算密集型的任務,就用多程序并發吧。