您好,登錄后才能下訂單哦!
這篇文章主要介紹“Python編程中Python與GIL互斥鎖的關系”,在日常操作中,相信很多人在Python編程中Python與GIL互斥鎖的關系問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Python編程中Python與GIL互斥鎖的關系”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Python 第一次發布是在 1991 年,當時的 CPU 都是單核,單核中,多線程主要為了一邊做IO,一邊做 CPU 計算而設計的,Python 編譯器是由 C 語言編寫的,因此也叫 CPython,那時候很多編程語言沒有自動內存管理的功能,為了實現自動垃圾回收,Python 為每一個對象進行了引用計數,當引用計數為 0 的時候說明該對象可以回收,從而釋放內存了,比如:
>>> import sys >>> data = { 'gzh': 'Python七號'} >>> var1 = data >>> sys.getrefcount(data) 3 >>>
這里 data 對象就有 3 個引用, 一個是本身,一個是變量 var1,一個是 getrefcount 函數的參數,如果此時又有一個線程引用了 data,那么引用計數再增加 1,如果某個線程使用了 data 后運行結束,那么引用計數就減少 1,多線程對同一個變量「引用計數」進行修改,就會遇到 race conditions(競爭),為了避免 race conditions,最簡單有效的辦法就是加一個互斥鎖。
如果對每一個對象都加鎖,有可能引發另一個問題,就是死鎖,而且頻繁的獲取和釋放會導致性能下降,最簡單有效的方法就是加一個解釋器鎖,線程在執行任何字節碼時都先獲取解釋器鎖,這就避免了死鎖,而且不會有太多的性能消耗。當時 CPU 都是單核,而且這種 GIL 設計簡單,并不會影響性能,因此一直沿用至今天。GIL 存在最主要的原因,就是因為 Python 的內存管理不是線程安全的,這就是 GIL 產生并存在的主要緣由。
CPU 進入多核時代后,可以同時做多個計算任務, GIL 才真正變成問題。在 1999 年,有個叫 Greg Stein 的大佬基于 Python 1.5 版本消除了 GIL,取代代之的是在可變數據結構上加上更細粒度的鎖,也提交了補丁用于去除對全局可變對象的依賴,然后在標準測試時表明去除 GIL 后單線程比不去除時慢了近 2 倍,測試的機器還是當時性能最好 Windows 機器。也就是說除去了 GIL 后,你使用 2 個 CPU 才能獲取比原來 1 個 CPU 稍微好一點的性能,這種提升明顯得不償失,Greg Stein 的嘗試也就失敗告終。
Python 之父 Guido van Rossum 也歡迎社區的志愿者去嘗試去除 GIL,只要不降低單線程的性能,但他也提到,去掉 GIL 不是一件容易的事。
Python 開發者郵件列表中也偶爾會有去除 GIL 的議題,但是以下需求必須滿足:
簡單。從長遠來看該方案必須是可實施、可維護的。
并發。去除 GIL 必須能提升多線程的性能。
速度。去除 GIL 不能降低單線程的性能。
滿足 CPython 的特性。該方案必須支持 CPython 的功能,比如 __del__
和弱引用。
API 的兼容性。該方案應與所有現有CPython擴展使用的宏在源方面兼容。
及時銷毀不可達對象,回收內存。
有序銷毀,比如不可達對象 X 引用了 A,那么應該在銷毀 A 之前先銷毀 X(有些垃圾回收算法并不能做到這一點)。
有些需求不容易被滿足,比如 4,5,7,目前,還沒有人滿足以上需求的同時去除 GIL 成功的。
這些年 Python 實在太火了,很多優秀的庫都是基于 CPython 進行編寫的,很多都是 90 年代的 C 擴展庫,如果要除去 GIL,那么很多基于 GIL 編寫的 C 擴展便無法使用,也就是去了 GIL,Python 生態有很多擴展或三方庫者無法使用。
還有一個很明顯的例子,Python 解釋器不止有 CPython,還有用 Java 編寫的 Python,.NET 實現的 IronPython,這些解釋器完全沒有 GIL,可是有多少人為它們編寫擴展呢?
Python 之所以如此火爆,與它有著豐富的三方庫開箱即用有著很大的關系,積重難返,去除 GIL 很困難。
Python3 在最開始時是有機會實現很多新功能,在此過程中,打破了一些現有的 C 擴展,然后需要更新和移植更改以配合 Python 3,這也是 Python3 一開始不被社區所接受的原因。
與 Python2 相比,刪除 GIL 將使 Python3 在單線程性能方面更慢,而且很多優秀的擴展將不能再使用,如果真的這樣,可以想象 Python3 不可能有未來,最終的結果是 Python3 仍然保持有 GIL。
但 Python3 也為現有的 GIL 帶來了重大改進,在 Python 3.2 版本中,確保了計算密集型線程和 I/O 密集型線程并存時, I/O 密集型長期獲取不到 GIL 而無法執行的問題,提升了多線程的性能。
到此,關于“Python編程中Python與GIL互斥鎖的關系”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。