熱線電話:13121318867

登錄
首頁精彩閱讀因為Python多線程自帶的bug,老板差點把我開了
因為Python多線程自帶的bug,老板差點把我開了
2022-08-17
收藏

作者:小K

來源:麥叔編程

?

上期的Python三分鐘留言區,有很多小伙伴想了解Python的GIL是個啥玩意。

但是想了解GIL到底是個啥,我們需要學習一些前置的知識。

這樣才能更好得了解GIL。

?

什么是線程安全

線程安全, 是指變量或方法(這些變量或方法是多線程共享的) 可以在多線程的環境下被安全有效的訪問。

太抽象了?我舉個例子:

假如今天中午12:00,在某平臺有1元搶茅臺活動,參加活動的茅臺就一瓶。

但是中午集結了好幾萬用戶在線等開搶信號,時間到了12:00:00,這些用戶瘋狂點擊屏幕搶購。

此時某平臺肯定要保證只有一個人能獲得活動茅臺,要不然平臺還不賠死。「這就是線程安全的概念?!?/span>

Python中的線程非安全

import threadingzero = 0def change_zero(): global zero for i in range(3000000):        zero += 1 zero -= 1th1 = threading.Thread(target = change_zero)th2 = threading.Thread(target = change_zero)th1.start()th2.start()th1.join()th2.join()print(zero)

我定義了一個函數change_zero對全局變量zero+1、-1操作。

還定義了兩個線程th1和th2去執行它3000000*2次。

每次+1、-1都會被執行的話,輸出的zero肯定還是0,

但是代碼執行之后...

好像根本不會還等于0。

所以我們推測,運行當中肯定有幾次+1,-1的操作沒有有效地被執行。(線程非安全)。

但是這樣的代碼投入生產肯定是有bug的,如果將這代碼用在一些金額結算上,那寫代碼的人肯定是頭鐵了。

?

那有什么辦法能拯救線程非安全的操作呢?

?

有個很常用的方法,那就是「加鎖」。

規避線程非安全操作

import threadinglock = threading.Lock() # 創建線程鎖zero = 0def change_zero():    global zero for i in range(3000000):        with lock:      # 把線程非安全操作加鎖            zero += 1 zero -= 1th1 = threading.Thread(target = change_zero)th2 = threading.Thread(target = change_zero)th1.start()th2.start()th1.join()th2.join()print(zero)

從上方代碼中,我們把zero += 1和zero -= 1這兩步操作進行加鎖。

?

類似于接力跑,只有從前一棒隊友手中接過接力棒,才能往下一棒隊友那邊跑,沒有完成接力棒交接則不能跑。

?

?

上下文管理器with lock在操作進行時會執行lock.acquire()拿到鎖,執行完畢后會將鎖釋放給下一個操作lock.release()。

?

運行上方加了鎖之后的代碼:

得到的結果都是0,沒再出現計算混亂的情況,這就從線程非安全轉變成線程安全操作了。

后記

看到這,你是否有疑問了?

Python不是有GIL護體嗎?怎么還會出現這種線程非安全的情況?

數據分析咨詢請掃描二維碼

若不方便掃碼,搜微信號:CDAshujufenxi

數據分析師資訊
更多

OK
客服在線
立即咨詢
日韩人妻系列无码专区视频,先锋高清无码,无码免费视欧非,国精产品一区一区三区无码
客服在線
立即咨詢