<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
前面提到了銀行轉賬這個場景,展示了一個比較耗時的轉賬操作。
這篇繼續轉帳,下面展示一段程式,多個執行緒的操作都更改了amount
變數導致執行結果不對的問題。
前文說了轉賬問題
下面展示另一種轉賬的方式:
import random import threading import datetime import time xuewei = {'balance': 157} # amount為負數即是轉出金額 def transfer(money): name = threading.current_thread().getName() print("%s 給xuewei轉賬 %s " % (name, money)) xuewei['balance'] += money print("xuewei賬戶餘額:", xuewei['balance']) lists = [-7, 20, -20, 7] # 4次轉賬的數額,負數為學委的賬戶轉出,正數為他人轉入。 # 建立4個任務給學委轉賬上面lists的金額 threads = [] for i in range(4): amount = lists[i] name = "t-" + str(i) print("%s 計劃轉賬 %s" % (name, amount)) mythread = threading.Thread(name=name, target=lambda: transfer(amount)) threads.append(mythread) # 開始轉賬 for t in threads: t.start() # 等待3秒讓上面的轉賬任務都完成,我們在看看賬戶餘額 time.sleep(3) print("-" * 16) print("學委賬戶餘額:", xuewei['balance'])
這裡啟動了4個執行緒,每個執行緒內有個lambda
表示式,分別於學委的賬戶進行轉賬,但是最後結果是185. 而不是157.
下面是執行結果:
PS: 這只是一種執行結果。多執行緒的執行結果不是永遠一樣的。
如何解決這個問題?
觀測結果我們發先amount
只保留了最後一個值。
好,下面改造一下:
import random import threading import datetime import time xuewei = {'balance': 157} lists = [-7, 20, -20, 7] # 4次轉賬的數額,負數為學委的賬戶轉出,正數為他人轉入。 def transfer(amount): name = threading.current_thread().getName() print("%s 給xuewei轉賬 %s " % (name,amount)) xuewei['balance'] += amount print("xuewei賬戶餘額:", xuewei['balance']) # 建立4個任務給學委轉賬上面lists的金額 for i in range(4): amount = lists[i] name = str(i) # mythread = threading.Thread(name=name, target=lambda: transfer(amount)) def event(): print("%s 計劃轉賬 %s" % (name, amount)) transfer(amount) mythread = threading.Thread(name=name, target=event) mythread.start() # 等待3秒讓上面的轉賬任務都完成,我們在看看賬戶餘額 time.sleep(3) print("-" * 16) print("學委賬戶餘額:", xuewei['balance'])
學委這裡加了一個event
函數,把轉賬計劃列印出來。
從下面的一次執行結果看,event函數的輸出結果沒錯,所有”計劃轉賬“金額都如預期[-7, 20, -20 7]。 問題是transfer函數再多執行緒執行的時候,我們發現amount被多執行緒競爭修改了:
使用者0轉賬金額變成20
使用者1轉賬金額變成-20
使用者2轉賬金額變成7
使用者3轉賬金額變成7
也就是說,amount
被後面的執行緒修改了,但是前面執行緒還沒有執行完。
使用者0應該轉賬-7的,中間還沒有執行完畢,結果被執行緒1修改了amount為20,使用者0繼續執行轉賬,餘額變成177. 其他依次推理。
amount
這個變數被多個執行緒競爭修改了,這個就是程式的共用變數。
到底如何解決?
方法非常簡單:直接幹掉共用變數。
下面就是消除共用變數的方法: 讓共用變成每個執行緒存取獨立執行空間
所以程式碼改動如下:
import random import threading import datetime import time xuewei = {'balance': 157} lists = [-7, 20, -20, 7] # 4次轉賬的數額,負數為學委的賬戶轉出,正數為他人轉入。 # 我們不要依賴amount變數了 def transfer(): name = threading.current_thread().getName() xuewei['balance'] += lists[int(name)] #通過執行緒名字來獲取對應金額 print("xuewei賬戶餘額:", xuewei['balance']) # 建立4個任務給學委轉賬上面lists的金額 threads = [] for i in range(4): amount = lists[i] name = str(i) print("%s 計劃轉賬 %s" % (name, amount)) # mythread = threading.Thread(name=name, target=lambda: transfer()) def event(): transfer() mythread = threading.Thread(name=name, target=event) threads.append(mythread) # 開始轉賬 for t in threads: t.start() # 等待3秒讓上面的轉賬任務都完成,我們在看看賬戶餘額 time.sleep(3) print("-" * 16) print("學委賬戶餘額:", xuewei['balance'])
執行結果如下:
上面的程式碼不管怎麼執行,執行多少次最後學委的賬戶都是157.
這次展示的另一種方式來避開多執行緒出現bug的方法,使用一個list下標跟執行緒名字一一對應,這樣只要是對應名字的執行緒拿到的數值不錯錯亂。
到此這篇關於Python執行緒之如何解決共用變數問題的文章就介紹到這了,更多相關Python執行緒解決共用變數問題內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45