日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

python全局解释锁_Python GIL 全局解释性锁介绍

發(fā)布時(shí)間:2025/4/16 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python全局解释锁_Python GIL 全局解释性锁介绍 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

什么是GIL

GIL (Global Interpreter Lock),全局解釋性鎖,它上鎖的對(duì)象是解釋器,而Python代碼的運(yùn)行需要解釋器進(jìn)行解釋成字節(jié)碼并提供虛擬機(jī)運(yùn)行,這么大粒度的鎖意味著,一個(gè)Python進(jìn)程內(nèi)的線程只有先獲得GIL,才能得到代碼執(zhí)行的機(jī)會(huì),這個(gè)鎖使得Python進(jìn)程的多線程無(wú)法利用多核cpu帶來(lái)性能提升。

但需要明確的一點(diǎn)是,GIL并不是Python的特性,而是CPython(最常用的Python解釋器)的特性。這意味著我們可以使用其他的Python解釋器從而繞過(guò)GIL的困擾,如JPython就沒(méi)有GIL。但由于CPython是大部分環(huán)境下默認(rèn)的Python解釋器,而且Python社區(qū)大部分第三方庫(kù)也依賴GIL這個(gè)特性提供的線程安全,由于這樣的歷史路徑依賴,我們對(duì)GIL是欲罷不能。

看見(jiàn)GIL

接下來(lái)我們通過(guò)幾個(gè)簡(jiǎn)單的例子來(lái)看看GIL對(duì)多核利用的影響

運(yùn)行如下代碼看看CPU的占用率

123456

def dead_loop():

while True:

pass

if __name__ == "__main__":

dead_loop()

測(cè)試的機(jī)器是個(gè)人 macbook pro,4個(gè)物理CPU,劃分為8個(gè)邏輯CPU;可以看到該程序的確是把單核的占用跑滿了;接著我們多開(kāi)一個(gè)線程一起跑dead_loop,線程是CPU調(diào)度的基本單位,按道理兩個(gè)線程應(yīng)該并行運(yùn)行,CPU占用應(yīng)該提高一倍;

12345678910111213

import threading

def dead_loop():

while True:

pass

if __name__ == "__main__":

t = threading.Thread(target=dead_loop)

t.start()

dead_loop()

t.join()

如圖,確實(shí)是運(yùn)行了兩個(gè)線程,但是只有一個(gè)線程是激活的,只跑滿一個(gè)核,CPU的占用率依舊是 1?8 左右 【因?yàn)橛衅渌脩舫绦?#xff0c;因此略高于 1?8 】。

作為對(duì)比,我們使用Golang跑兩個(gè)線程看看。

123456789101112131415

package main

func main(){

ch := make(chan int, 0)

k := 1

for i:=0; i<2; i++{

go func() {

for ; k>0 ; {

}

}()

}

}

可以看到,Golang的確按照預(yù)期的那樣,兩個(gè)線程在死循環(huán)運(yùn)行,CPU占用率達(dá)到總的 1?4 左右。

從以上的示例我們可以發(fā)現(xiàn),GIL確實(shí)限制了Python進(jìn)程的多線程對(duì)多核CPU的利用。

怎么辦

使用其他解釋器

GIL只是CPython的產(chǎn)物,像JPython和IronPython這樣的解釋器由于實(shí)現(xiàn)語(yǔ)言的特性,它們不需要GIL的幫助,但是由于用來(lái)Java/C#用于解釋器的實(shí)現(xiàn),它們也失去了利用社區(qū)眾多C語(yǔ)言模塊有用特性的機(jī)會(huì)。【Done is better than perfect】

用multiprocessing替代Thread

multiprocessing庫(kù)的出現(xiàn)很大程度上是為了彌補(bǔ)thread庫(kù)因?yàn)镚IL而低效的缺陷,它使用了多進(jìn)程而不是多線程,而每個(gè)進(jìn)程有自己獨(dú)立的GIL,因此不會(huì)出現(xiàn)進(jìn)程間的GIL爭(zhēng)搶。

但是multiprocessing也有其他麻煩,比如本來(lái)的多線程的同步和通信機(jī)制在多進(jìn)程下就用不了了,拿計(jì)數(shù)器來(lái)舉例子,如果要多個(gè)線程同時(shí)累加一個(gè)變量,對(duì)于thread來(lái)說(shuō),聲明一個(gè)global變量,加個(gè)訪問(wèn)鎖即可搞定;但是由于進(jìn)程有自己獨(dú)立的地址空間,無(wú)法直接訪問(wèn)彼此的變量數(shù)據(jù),因此這個(gè)共享數(shù)據(jù)就必須從進(jìn)程里提出到更高層的存儲(chǔ)中,苦呀。

看看多進(jìn)程的CPU占用

12345678910111213

import multiprocessing

def dead_loop():

while True:

pass

if __name__ == "__main__":

p = multiprocessing.Process(target=dead_loop)

p.start()

dead_loop()

p.join()

開(kāi)了兩個(gè)進(jìn)程,俱跑滿了單核

社區(qū)的努力

Python社區(qū)也一直在努力地改進(jìn)GIL,甚至嘗試去除GIL

將切換粒度從基于opcode計(jì)數(shù)改成基于時(shí)間片計(jì)數(shù)

避免最近一次釋放GIL鎖的線程再次被立即調(diào)度

新增線程優(yōu)先級(jí)功能(高優(yōu)先級(jí)可以迫使其他線程釋放所持有的GIL鎖)

總結(jié)

Python GIL是功能與性能之間權(quán)衡后的產(chǎn)物,雖然它的存在導(dǎo)致Python單進(jìn)程的CPU密集型多線程形同虛設(shè),但它有其存在的合理性【簡(jiǎn)單有用地實(shí)現(xiàn)線程安全】,也有其較難改變的客觀因素【歷史路徑依賴】。

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的python全局解释锁_Python GIL 全局解释性锁介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。