溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python編程中Python與GIL互斥鎖的關系

發(fā)布時間:2021-09-14 17:32:55 來源:億速云 閱讀:115 作者:chen 欄目:開發(fā)技術

這篇文章主要介紹“Python編程中Python與GIL互斥鎖的關系”,在日常操作中,相信很多人在Python編程中Python與GIL互斥鎖的關系問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Python編程中Python與GIL互斥鎖的關系”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

GIL 的起源

Python 第一次發(fā)布是在 1991 年,當時的 CPU 都是單核,單核中,多線程主要為了一邊做IO,一邊做 CPU 計算而設計的,Python 編譯器是由 C 語言編寫的,因此也叫 CPython,那時候很多編程語言沒有自動內存管理的功能,為了實現(xiàn)自動垃圾回收,Python 為每一個對象進行了引用計數(shù),當引用計數(shù)為 0 的時候說明該對象可以回收,從而釋放內存了,比如:

>>> import sys
>>> data = { 'gzh': 'Python七號'}
>>> var1 = data
>>> sys.getrefcount(data)
3
>>>

這里 data 對象就有 3 個引用, 一個是本身,一個是變量 var1,一個是 getrefcount 函數(shù)的參數(shù),如果此時又有一個線程引用了 data,那么引用計數(shù)再增加 1,如果某個線程使用了 data 后運行結束,那么引用計數(shù)就減少 1,多線程對同一個變量「引用計數(shù)」進行修改,就會遇到 race conditions(競爭),為了避免 race conditions,最簡單有效的辦法就是加一個互斥鎖。

如果對每一個對象都加鎖,有可能引發(fā)另一個問題,就是死鎖,而且頻繁的獲取和釋放會導致性能下降,最簡單有效的方法就是加一個解釋器鎖,線程在執(zhí)行任何字節(jié)碼時都先獲取解釋器鎖,這就避免了死鎖,而且不會有太多的性能消耗。當時 CPU 都是單核,而且這種 GIL 設計簡單,并不會影響性能,因此一直沿用至今天。GIL 存在最主要的原因,就是因為 Python 的內存管理不是線程安全的,這就是 GIL 產生并存在的主要緣由。

嘗試消除 GIL

CPU 進入多核時代后,可以同時做多個計算任務, GIL 才真正變成問題。在 1999 年,有個叫 Greg Stein 的大佬基于 Python 1.5 版本消除了 GIL,取代代之的是在可變數(shù)據結構上加上更細粒度的鎖,也提交了補丁用于去除對全局可變對象的依賴,然后在標準測試時表明去除 GIL 后單線程比不去除時慢了近 2 倍,測試的機器還是當時性能最好 Windows 機器。也就是說除去了 GIL 后,你使用 2 個 CPU 才能獲取比原來 1 個 CPU 稍微好一點的性能,這種提升明顯得不償失,Greg Stein 的嘗試也就失敗告終。

Python 之父 Guido van Rossum 也歡迎社區(qū)的志愿者去嘗試去除 GIL,只要不降低單線程的性能,但他也提到,去掉 GIL 不是一件容易的事。

Python 開發(fā)者郵件列表中也偶爾會有去除 GIL 的議題,但是以下需求必須滿足:

  • 簡單。從長遠來看該方案必須是可實施、可維護的。

  • 并發(fā)。去除 GIL 必須能提升多線程的性能。

  • 速度。去除 GIL 不能降低單線程的性能。

  • 滿足 CPython 的特性。該方案必須支持 CPython 的功能,比如 __del__ 和弱引用。

  • API 的兼容性。該方案應與所有現(xiàn)有CPython擴展使用的宏在源方面兼容。

  • 及時銷毀不可達對象,回收內存。

  • 有序銷毀,比如不可達對象 X 引用了 A,那么應該在銷毀 A 之前先銷毀 X(有些垃圾回收算法并不能做到這一點)。

有些需求不容易被滿足,比如 4,5,7,目前,還沒有人滿足以上需求的同時去除 GIL 成功的。

積重難返

這些年 Python 實在太火了,很多優(yōu)秀的庫都是基于 CPython 進行編寫的,很多都是 90 年代的 C 擴展庫,如果要除去 GIL,那么很多基于 GIL 編寫的 C 擴展便無法使用,也就是去了 GIL,Python 生態(tài)有很多擴展或三方庫者無法使用。

還有一個很明顯的例子,Python 解釋器不止有 CPython,還有用 Java 編寫的 Python,.NET 實現(xiàn)的 IronPython,這些解釋器完全沒有 GIL,可是有多少人為它們編寫擴展呢?

Python 之所以如此火爆,與它有著豐富的三方庫開箱即用有著很大的關系,積重難返,去除 GIL 很困難。

為什么 Python3 一開始時不去除 GIL

Python3 在最開始時是有機會實現(xiàn)很多新功能,在此過程中,打破了一些現(xiàn)有的 C 擴展,然后需要更新和移植更改以配合 Python 3,這也是 Python3 一開始不被社區(qū)所接受的原因。

與 Python2 相比,刪除 GIL 將使 Python3 在單線程性能方面更慢,而且很多優(yōu)秀的擴展將不能再使用,如果真的這樣,可以想象 Python3 不可能有未來,最終的結果是 Python3 仍然保持有 GIL。

但 Python3 也為現(xiàn)有的 GIL 帶來了重大改進,在 Python 3.2 版本中,確保了計算密集型線程和 I/O 密集型線程并存時, I/O 密集型長期獲取不到 GIL 而無法執(zhí)行的問題,提升了多線程的性能。

到此,關于“Python編程中Python與GIL互斥鎖的關系”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI