Python多任務編程——線程間共用變數

相關標籤:1.使用Python增強Web功能
2.Shodan與Python API

問題:線程間共用全域變數資料出錯



import threading

g_num = 0


def task1 ():
for i in range ( 1000000 ):
global g_num
g_num += 1
print ( 'TASK1:' , g_num )

def task2 ():
for i in range ( 1000000 ):
global g_num
g_num += 1
print ( 'TASK2:' , g_num )


if __name__ == "__main__" :
first = threading.Thread ( target = task1 ) _ _
second = threading.Thread ( target = task2 ) _ _
first.start ( ) _
second.start ( ) _


運行結果:




理論上,實現了100萬次迴圈,每次迴圈對全域變數加1,最終結果應為2000000。實際結果如上圖所示。

原因:



兩個線程同時操作全域變數。線程1讀取全域變數時,線程2也在讀取全域變數。對變數進行操作時,讀取的是原始變數,而非操作後的變數。因為線程1對變數的操作未提交,所以線程2讀取的仍是之前的變數值。
解決方案

使用進程同步,確保同一時刻只有一個線程操作資料。

1. 使用 join() 方法

import threading

g_num = 0


def task1 ():
for i in range ( 1000000 ):
global g_num
g_num += 1
print ( 'TASK1:' , g_num )

def task2 ():
for i in range ( 1000000 ):
global g_num
g_num += 1
print ( 'TASK2:' , g_num )


if __name__ == "__main__" :
first = threading.Thread ( target = task1 ) _ _
second = threading.Thread ( target = task2 ) _ _
first.start ( ) _
first.join ( ) _
second.start ( ) _
結果:



原理:程式運行時加入 first.join() 等待,第一個線程完成後第二個線程才開始運行,確保同一時刻只有一個線程操作變數。
線程同步:一個任務執行完畢後再執行另一個任務,同一時刻只有一個任務在執行。

2. 互斥鎖

import threading

g_num = 0

# Creating a mutex is essentially a function via
LOCK = threading.Lock ( ) _
def task1 ():
# lock
LOCK.acquire ( ) _
for i in range ( 1000000 ):
global g_num
g_num += 1
print ( 'TASK1:' , g_num )
# release lock
LOCK.release ( ) _


def task2 ():
LOCK.acquire ( ) _
for i in range ( 1000000 ):
global g_num
g_num += 1
print ( 'TASK2:' , g_num )
LOCK.release ( ) _


if __name__ == "__main__" :
first = threading.Thread ( target = task1 ) _ _
second = threading.Thread ( target = task2 ) _ _
first.start ( ) _
second.start ( ) _

結果:





原理:對共用資料加鎖,同一時刻只有一個線程進行操作,多個線程共同搶佔,使用 threading 中的鎖函數率先搶佔成功。運行第一個線程時,先用 lock.acquire() 鎖定當前線程,期間其他線程無法運行。迴圈結束後,使用 lock.release() 釋放當前線程,之後其他線程才能操作。確保同一時刻只有一個線程在運行。
但是,互斥鎖在一定程度上影響了代碼的執行效率,將多任務變為單任務執行,還可能引發死結問題(由於鎖未及時釋放導致)。

著作權聲明:本文由阿里雲實名註冊使用者貢獻,著作權歸作者所有。阿里雲開發人員社區不擁有著作權,也不承擔相應法律責任。具體規則請參閱《阿里雲開發人員社區使用者服務協議》和《阿里雲開發人員社區智慧財產權保護指引》。如您發現本社區存在涉嫌抄襲的內容,請填寫侵權投訴表進行舉報。一經核實,本社區將立即刪除涉嫌侵權內容。

相關文章

探索更多特惠

  1. 簡訊服務(SMS)與郵件服務

    50000封郵件包低至1.99美元,120條簡訊僅需1.00美元

phone 聯絡我們
Hi, I'm Alibaba Cloud AI Assistant!
I can help with questions and solutions.