併發編程-進~線程-01GIL全局解釋器鎖

一丶什麼是GIL鎖

python解釋器有不少種 最多見的就是Cpython解釋器
GIL本質也是一把互斥鎖:將併發變成串行犧牲效率保證數據的安全
用來阻止同一個進程下的多個線程的同時執行(同一個進程內多個線程沒法實現並行可是能夠實現併發python

在Cpython解釋器中,同一個進程下開啓的多線程,同一時刻只能有一個線程執行,沒法利用多核優點安全

二丶爲何存在GIL

GIL的存在是由於CPython解釋器的內存管理不是線程安全的多線程

垃圾回收機制自己就是python解釋器開啓的一個進程必然除了主線程外還會有一個垃圾回收線程併發

GIL和垃圾回收機制

一個cpython開啓進程中一定有一個解釋器線程, 一個垃圾回收機制線程, 當前有一個變量a 等於1,就是申請一分內存空間,把1放進去,而後把a指向這個內存位置app

在這過程當中會出現這麼一種狀況: 當建立出 一個空間,把值爲1放進去時候, 同時垃圾回收線程起來了,而後它掃描到a這個時候他尚未對值1對它進行綁定關係 ,垃圾回收機制判斷它爲一個無用的變量,而後把它刪除了, 以後當要指向的操做時候,忽然發現沒有了變量a, 這時候就出現了報錯!測試

其實GIL的出現就是爲了解決垃圾回收機制 , 讓數據更加的安全!ui

它的存在會加把鎖,好比當前 某線程搶到了GIL鎖, 而後對變量進行建立綁定時候 別的線程(這邊好比垃圾回收機制) 它搶不到當前的這把鎖, 它會等待前個線程結束釋放鎖後強鎖成功纔會運行, 這樣就不會出現剛纔的那種臨界狀況.線程

兩個常見的錯誤點

1.GIL是python的特色嗎?code

不是! 它是CPython的特色!對象

2.單進程多個多個線程沒法利用多核優點是全部語言的通病嗎?

不是! 它只是全部解釋型語言的通病,就好比 PHP丶 Python

三丶GIL和Lock

GIL保護的是解釋器級的數據,保護用戶本身的數據則須要本身加鎖處理

gil鎖

四丶python的多線程是否有用

研究python的多線程是否有用須要分狀況討論
四個任務 計算密集型的 10s
單核狀況下
開線程更省資源
多核狀況下
開進程 10s
開線程 40s

四個任務 IO密集型的
單核狀況下
開線程更節省資源
多核狀況下
開線程更節省資源

4.1測試代碼

計算密集型

# 計算密集型
from multiprocessing import Process
from threading import Thread
import os,time
def work():
    res=0
    for i in range(100000000):
        res*=i


if __name__ == '__main__':
    l=[]
    print(os.cpu_count())  # 本機爲6核
    start=time.time()
    for i in range(6):
        # p=Process(target=work) #耗時  4.732933044433594
        p=Thread(target=work) #耗時 22.83087730407715
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))

IO密集型

from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
    time.sleep(2)

if __name__ == '__main__':
    l=[]
    print(os.cpu_count()) #本機爲6核
    start=time.time()
    for i in range(4000):
        p=Process(target=work) #耗時9.001083612442017s多,大部分時間耗費在建立進程上
        # p=Thread(target=work) #耗時2.051966667175293s多
        l.append(p)
        p.start()
    for p in l:
        p.join()
    stop=time.time()
    print('run time is %s' %(stop-start))
python的多線程到底有沒有用
須要看狀況而定  而且確定是有用的

多進程+多線程配合使用

五丶pythonGIL鎖

from threading import Thread
import time

n = 100

def task():
    global n
    tmp = n
    # time.sleep(1)
    n = tmp -1

t_list = []
for i in range(100):
    t = Thread(target=task)
    t.start()
    t_list.append(t)

for t in t_list:
    t.join()

print(n)

過程分析:全部線程搶的是GIL鎖,或者說全部線程搶的是執行權限   線程1搶到GIL鎖,拿到執行權限,開始執行,而後加了一把Lock,尚未執行完畢,即線程1還未釋放Lock,有可能線程2搶到GIL鎖,開始執行,執行過程當中發現Lock尚未被線程1釋放,因而線程2進入阻塞,被奪走執行權限,有可能線程1拿到GIL,而後正常執行到釋放Lock。。。這就致使了串行運行的效果 鎖一般被用來實現對共享資源的同步訪問。爲每個共享資源建立一個Lock對象,當你須要訪問該資源時,調用acquire方法來獲取鎖對象(若是其它線程已經得到了該鎖,則當前線程需等待其被釋放),待資源訪問完後,再調用release方法釋放鎖:

相關文章
相關標籤/搜索