Python如何規避全局解釋器鎖(GIL)帶來的限制


 

編程語言分類概念介紹(編譯型語言、解釋型語言、靜態類型語言、動態類型語言概念與區別)

https://www.cnblogs.com/zhoug2020/p/5972262.html

 

Python解釋器

一般使用的Python解釋器CPython:是用C語言實現Pyhon,是目前應用最廣泛的解釋器。最新的語言特性都是在這個上面先實現,基本包含了所有第三方庫支持,但是CPython有幾個缺陷,一是全局鎖使Python在多線程效能上表現不佳,二是CPython無法支持JIT(Just-in-time compliation即時編譯),導致其執行速度不及Java和Javascipt等語言。於是出現了Pypy。

Pypy:是用Python自身實現的解釋器。針對CPython的缺點進行了各方面的改良,性能得到很大的提升。最重要的一點就是Pypy集成了JIT。但是,Pypy無法支持官方的C/Python API,導致無法使用例如Numpy,Scipy等重要的第三方庫。(還有JPython,IronPython等)

 

全局解釋器鎖

全局解釋器鎖(Global Interpreter Lock)是Python用於同步線程的工具,使得任何時刻僅有一個線程在執行。 

 

Python GIL被動釋放機制(搶占機制)

如果一個線程不間斷地在 Python 2 中運行100次解釋器的計步(ticks)(可以通過sys.setcheckinterval()設置計步長度),或者不間斷地在 Python 3 運行15 毫秒,那么它便會放棄 GIL,而其他線程可以運行。

 

全局解釋器鎖帶來的問題

多線程Python程序無法充分利用多個CPU核心帶來的優勢。

(主要影響CPU密集型程序,I/O密集型程序使用多線程一般是明智的選擇)

 

解決方法

1,使用多進程

原理:每個進程分配不同的解釋器,有單獨的GIL。

缺點:額外產生數據序列化與通信的開銷。

注意點:待執行操作需包含在以def語句定義的Python函數中(即,在這里lambda,閉包,可調用實例都是不可以的),而且函數參數和返回值必須兼容pickle編碼。

使用方法:廖雪峰Python教程-多進程部分

 

2,使用C語言擴展模塊

原理:C語言擴展程序的執行保持與Python解釋器隔離,在C代碼中釋放GIL。

缺點:調用C函數時GIL會被鎖定,若阻塞,解釋器無法釋放GIL。

注意點:確保C代碼可以獨立於Python執行。(不使用Python的數據結構,也不調用Python的C語言API)

使用方法:在C代碼中插入特殊的宏或是使用其他工具來訪問C代碼,如ctypes庫或者Cython。(ctypes默認會在調用C代碼時自動釋放GIL)

使用ctypes訪問C代碼教程

 

3,選用其他沒有GIL的解釋器代替CPython

原理:使用沒有GIL的解釋器實現。

缺點:不完全兼容。

使用方法:目前Jython和IronPython沒有GIL。

Jython文檔IronPython官網

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM