1. 程式人生 > >python使用多執行緒(二)

python使用多執行緒(二)

介紹

其實python在同一時間只允許一個執行緒執行一個任務,其它執行緒都會被鎖住。多執行緒其實就是不停的執行緒切換,給人以多執行緒的現象。python中實現這個功能的結構稱為全域性直譯器鎖(GIL)。

如果任務都是相同的,比如一直執行total=total+1,這時其實多執行緒幫不了太多忙,即使單執行緒也可以完成這個工作,因為單執行緒在處理這個操作的時候,基本上沒有阻礙和停滯。不像上次舉的汽車裝配的例子,當其中一個工位被佔用的時候,這時多執行緒可以執行另外兩個操作,從而加快整體的速度。

如果遇到這種情況,可以考慮多核操作。每個核有單獨的邏輯空間,不同核內可以在相同時間同時執行一個執行緒。

Python中多執行緒之lock()

這是鎖的概念,首先直觀的看下沒有鎖的狀態:

import threading

def job1():
    global A
    for i in range(10):
        A+=4
        print('job1',A)

def job2():
    global A
    for i in range(10):
        A+=10
        print('job2',A)


if __name__=='__main__':
    A=0
    t1=threading.Thread(target=job1)
    t2 = threading.Thread(target=job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

輸出結果:

job1 4
job1 8
job1 12
job1 16
job1 20
job1 24
job2 34
job1 38
job2 48
job1 52
job2 62
job1 66
job2 76
job1 80
job2 90
job2 100
job2 110
job2 120
job2 130
job2 140

從結果上可以看出,輸出的比較亂,這是因為在t1沒有計算完成時,t2也開始了計算,這就導致輸出比較亂,有交叉和重疊。

加上鎖之後:

import threading

def job1():
    global A,lock
    lock.acquire()
    for i in range(10):
        A+=4
        print('job1',A)
    lock.release()

def job2():
    global A,lock
    lock.acquire()
    for i in range(10):
        A+=10
        print('job2',A)
    lock.release()

if __name__=='__main__':
    lock=threading.Lock()
    A=0
    t1=threading.Thread(target=job1)
    t2 = threading.Thread(target=job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

輸出結果:

job1 4
job1 8
job1 12
job1 16
job1 20
job1 24
job1 28
job1 32
job1 36
job1 40
job2 50
job2 60
job2 70
job2 80
job2 90
job2 100
job2 110
job2 120
job2 130
job2 140

可以看出job1和job2之間互不干涉,這是因為lock可以鎖住執行緒,基本思想就是,在執行完job1之前,該執行緒不會去執行其它操作,只會執行job1,當job1完成後開始解鎖,這個時候執行緒才會去執行job2,最終輸出的是有序的資料。