欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python全局解釋器GIL鎖機制詳解

 更新時間:2022年12月19日 13:59:04   作者:敲代碼敲到頭發(fā)茂密  
我們要知道一點GIL并不是Python的特性,它是Python解釋器Cpython引入的一個概念,下面這篇文章主要給大家介紹了關于python全局解釋器GIL鎖機制的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

一、GIL全局解釋器鎖

1、GIL鎖不是python的特點。而是cpython的特點。

2、在cpython解釋器中,GIL是一把互斥鎖,用來保證進程中同一個時刻只有一個線程在執(zhí)行。

3、在沒有GIL鎖的情況下,有可能多線程在執(zhí)行一個代碼的同時,垃圾回收機制對所執(zhí)行代碼的變量直接進行回收,其他的線程再使用該變量時會導致運行錯誤。

二、為什么會有GIL鎖?

python使用引用計數(shù)為主,標記清楚和隔代回收為輔來進行內(nèi)存管理。所有python腳本中創(chuàng)建的對象,都會配備一個引用計數(shù),來記錄有多少個指針來指向它。當對象的引用技術為0時,會自動釋放其所占用的內(nèi)存。

假設有2個python線程同時引用一個數(shù)據(jù)(a=100,引用計數(shù)為1),

2個線程都會去操作該數(shù)據(jù),由于多線程對同一個資源的競爭,實際上引用計數(shù)為3,

但是由于沒有GIL鎖,導致引用計數(shù)只增加1(引用計數(shù)為2)

這造成的后果是,當?shù)?個線程結束時,會把引用計數(shù)減少為1;當?shù)?個線程結束時,會把引用計數(shù)減少為0;

當下一個線程再次視圖訪問這個數(shù)據(jù)時,就無法找到有效的內(nèi)存了**

三、多線程無法利用多核優(yōu)勢?

由于GIL鎖的存在,即使是多個線程處理任務,但是最終只有一個線程在工作,那么是不是多線程真的一點用處都沒有了呢?

對于需要執(zhí)行的任務來說,分為兩種:計算密集型、IO 密集型

假如一個計算密集型的任務需要10s的執(zhí)行時間,總共有4個這樣的任務

在 4核及以上的情況下:
多進程:需要開啟 4 個進程,但是 4 個 CPU 并行,最終只需要消耗 10s 多一點的時間。
多線程:只需要開1 個進程,這個進程開啟 4 個線程,開啟線程所消耗的資源很少,但是由于最終執(zhí)行是只有一個 CPU 可以工作,所以最終消耗 40s 多的時間。

假如是多個 IO密集型 的任務

CPU 大多數(shù)時間是處于閑置狀態(tài),頻繁的切換

多進程:進程進行切換需要消耗大量資源
多線程:線程進行切換并不需要消耗大量資源

計算密集型和IO密集型

計算密集型:要進行大量的數(shù)值計算,例如進行上億的數(shù)字計算、計算圓周率、對視頻進行高清解碼等等。這種計算密集型任務雖然也可以用多任務完成,但是花費的主要時間在任務切換的時間,此時CPU執(zhí)行任務的效率比較低。

IO密集型:涉及到網(wǎng)絡請求(time.sleep())、磁盤IO的任務都是IO密集型任務,這類任務的特點是CPU消耗很少,任務的大部分時間都在等待IO操作完成(因為IO的速度遠遠低于CPU和內(nèi)存的速度)。對于IO密集型任務,任務越多,CPU效率越高,但也有一個限度。

計算密集型——采用多進程

執(zhí)行時間為: 4.062887668609619

from multiprocessing import Process
import time

def func1():
    sum=0
    for i in range(100000000):
        sum+=1
    print(sum)

if __name__ == '__main__':

    now=time.time()
    l=[]
    for i in range(10):
        p=Process(target=func1)
        p.start()
        l.append(p)
    for p in l:
        p.join()
    end=time.time()
    print('執(zhí)行時間為:',end-now)

計算密集型——采用多線程

執(zhí)行時間為: 27.6159188747406

from threading import Thread
import time

def func1():
    sum=0
    for i in range(100000000):
        sum+=1
    print(sum)

if __name__ == '__main__':

    now=time.time()
    l=[]
    for i in range(10):
        p=Thread(target=func1)
        p.start()
        l.append(p)
    for p in l:
        p.join()
    end=time.time()
    print('執(zhí)行時間為:',end-now)

IO密集型——采用多進程

執(zhí)行時間為: 5.388434886932373

from multiprocessing import Process
import time

def func1():
    time.sleep(2)

if __name__ == '__main__':

    now=time.time()
    l=[]
    for i in range(100):
        p=Process(target=func1)
        p.start()
        l.append(p)
    for p in l:
        p.join()
    end=time.time()
    print('執(zhí)行時間為:',end-now)

IO密集型——采用多線程

執(zhí)行時間為: 2.0174973011016846

from threading import Thread
import time

def func1():
    time.sleep(2)

if __name__ == '__main__':

    now=time.time()
    l=[]
    for i in range(100):
        p=Thread(target=func1)
        p.start()
        l.append(p)
    for p in l:
        p.join()
    end=time.time()
    print('執(zhí)行時間為:',end-now)

四、總結

對于IO密集型應用,即便有GIL存在,由于IO操作會導致GIL釋放,其他線程能夠獲得執(zhí)行權限。由于多線程的通訊成本低于多進程,因此偏向使用多線程。

對于計算密集型應用,由于CPU一直處于被占用狀態(tài),GIL鎖直到規(guī)定時間才會釋放,然后才會切換狀態(tài),導致多線程處于絕對的劣勢,此時可以采用多進程+協(xié)程。

到此這篇關于python全局解釋器GIL鎖機制的文章就介紹到這了,更多相關python GIL鎖詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論