04.python-多執行緒

Groot發表於2019-06-04

介紹

執行緒(Thread)是作業系統能夠進行運算排程的最小單位。它被包含在程式中,是程式中的實際運作單位。一個程式中可以併發多個執行緒,每條執行緒並行執行不同的任務。同一程式中的多個執行緒共享程式中的全部系統資源。

python中的多執行緒因為全域性直譯器鎖GIL的原因限制同一時刻只能由一個執行緒執行,無法發揮多核CPU的優勢【當然這是在預設直譯器CPython中的缺陷,在JPython中沒有GIL的問題,以下基於CPython直譯器】。所以:GIL並不是python的特性,python也不依賴於GIL。說了那麼多,那麼python中的多執行緒是不是沒用了?

答案當然不是。這取決於執行緒執行的場景是什麼?是做計算(計算密集型)還是輸入輸出(I/O密集型),針對不同的場景使用不同的方法。多核心CPU可以有多個核心並行完成計算,所以多核提升的是計算效能,但每個CPU一旦遇到I/O阻塞,仍然需要等待,所以多核對I/O密集型任務沒有太大的提升,多執行緒適合處理I/0密集型程式,如檔案讀寫,web請求,資料庫請求等。

使用

以下演示使用多執行緒對一個變數值進行修改,在迴圈的次數不多時修改後變數的值是符合預期的,當增加迴圈次數後,變數最終的值並不符合預期。由此可見:執行緒之間資源是存在競爭的,修改同一份資源必須加互斥鎖,同時需要避免死鎖。

# coding=utf-8
import threading

# 定義一個欄位。多執行緒執行+1操作
balance = 0

def worker1():
    global balance
    for i in range(1000):
        balance += 1
    print('執行緒1執行完成,balance='+str(balance))

def worker2():
    global balance
    for i in range(1000):
        balance += 1
    print('執行緒2執行完成,balance='+str(balance))

def main():
    # 構造執行緒物件
    t1 = threading.Thread(target=worker1)
    t2 = threading.Thread(target=worker2)
    # 開始執行
    t1.start()
    t2.start()

    """
    迴圈次數為1000時,程式輸出:
        執行緒1執行完成,balance=1000
        執行緒2執行完成,balance=2000
    迴圈次數為1000000時,程式輸出:
        執行緒1執行完成,balance=1180919
        執行緒2執行完成,balance=1179703
    """    

if __name__ == '__main__':
    main()

要想解決以下的問題,需要使用執行緒的鎖物件,只需要對worker1和woker2方法進行修改。

# 建立一個互斥鎖,預設是未鎖定狀態
mutex = threading.Lock()

def worker1():
    global balance
    for i in range(1000000):
        mutex.acquire()
        balance += 1
        mutex.release()
    print('執行緒1執行完成,balance=' + str(balance))

def worker2():
    global balance
    for i in range(1000000):
        mutex.acquire()
        balance += 1
        mutex.release()
    print('執行緒2執行完成,balance=' + str(balance))

"""
加了互斥鎖之後的輸出:
    執行緒1執行完成,balance=1941343
    執行緒2執行完成,balance=2000000
"""

特點:

  • 執行緒執行的順序是不確定的
  • 主執行緒【程式】會等待所有子執行緒結束後才會退出,主執行緒【程式】結束麼子執行緒必然結束
  • 執行緒間共享資源
  • 修改資源必要時需要加鎖,同時避免死鎖
  • 佔用的資源比程式少
  • 執行緒並不是越多越快
  • 由於GIL的原因,多執行緒並不是真正的併發,只是交替執行
本作品採用《CC 協議》,轉載必須註明作者和本文連結
死磕,不要放棄,終將會有所收穫。

相關文章