亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python線程之如何解決共享變量問題

 更新時間:2022年02月24日 10:16:16   作者:雷學(xué)委  
這篇文章主要介紹了Python線程之如何解決共享變量問題,掐滅問我們學(xué)習(xí)了銀行轉(zhuǎn)賬的這個場景,本文解決上次多個線程的操作都更改了amount變量導(dǎo)致運行結(jié)果不對的問題,需要的朋友可以參考一下

前面提到了銀行轉(zhuǎn)賬這個場景,展示了一個比較耗時的轉(zhuǎn)賬操作。

這篇繼續(xù)轉(zhuǎn)帳,下面展示一段程序,多個線程的操作都更改了amount變量導(dǎo)致運行結(jié)果不對的問題。

前文說了轉(zhuǎn)賬問題

下面展示另一種轉(zhuǎn)賬的方式:

import random
import threading
import datetime
import time

xuewei = {'balance': 157}


# amount為負(fù)數(shù)即是轉(zhuǎn)出金額
def transfer(money):
? ? name = threading.current_thread().getName()
? ? print("%s 給xuewei轉(zhuǎn)賬 %s " % (name, money))
? ? xuewei['balance'] += money
? ? print("xuewei賬戶余額:", xuewei['balance'])


lists = [-7, 20, -20, 7] ?# 4次轉(zhuǎn)賬的數(shù)額,負(fù)數(shù)為學(xué)委的賬戶轉(zhuǎn)出,正數(shù)為他人轉(zhuǎn)入。
# 創(chuàng)建4個任務(wù)給學(xué)委轉(zhuǎn)賬上面lists的金額
threads = []
for i in range(4):
? ? amount = lists[i]
? ? name = "t-" + str(i)
? ? print("%s 計劃轉(zhuǎn)賬 %s" % (name, amount))
? ? mythread = threading.Thread(name=name, target=lambda: transfer(amount))
? ? threads.append(mythread)

# 開始轉(zhuǎn)賬
for t in threads:
? ? t.start()

# 等待3秒讓上面的轉(zhuǎn)賬任務(wù)都完成,我們在看看賬戶余額
time.sleep(3)
print("-" * 16)
print("學(xué)委賬戶余額:", xuewei['balance'])

這里啟動了4個線程,每個線程內(nèi)有個lambda表達(dá)式,分別于學(xué)委的賬戶進(jìn)行轉(zhuǎn)賬,但是最后結(jié)果是185. 而不是157.

下面是運行結(jié)果:

PS: 這只是一種運行結(jié)果。多線程的運行結(jié)果不是永遠(yuǎn)一樣的。

如何解決這個問題?

觀測結(jié)果我們發(fā)先amount只保留了最后一個值。

好,下面改造一下:

import random
import threading
import datetime
import time

xuewei = {'balance': 157}

lists = [-7, 20, -20, 7] ?# 4次轉(zhuǎn)賬的數(shù)額,負(fù)數(shù)為學(xué)委的賬戶轉(zhuǎn)出,正數(shù)為他人轉(zhuǎn)入。


def transfer(amount):
? ? name = threading.current_thread().getName()
? ? print("%s 給xuewei轉(zhuǎn)賬 %s " % (name,amount))
? ? xuewei['balance'] += amount
? ? print("xuewei賬戶余額:", xuewei['balance'])


# 創(chuàng)建4個任務(wù)給學(xué)委轉(zhuǎn)賬上面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 計劃轉(zhuǎn)賬 %s" % (name, amount))
? ? ? ? transfer(amount)
? ? mythread = threading.Thread(name=name, target=event)
? ? mythread.start()


# 等待3秒讓上面的轉(zhuǎn)賬任務(wù)都完成,我們在看看賬戶余額
time.sleep(3)
print("-" * 16)
print("學(xué)委賬戶余額:", xuewei['balance'])

學(xué)委這里加了一個event函數(shù),把轉(zhuǎn)賬計劃打印出來。

從下面的一次運行結(jié)果看,event函數(shù)的輸出結(jié)果沒錯,所有”計劃轉(zhuǎn)賬“金額都如預(yù)期[-7, 20, -20 7]。 問題是transfer函數(shù)再多線程執(zhí)行的時候,我們發(fā)現(xiàn)amount被多線程競爭修改了:

用戶0轉(zhuǎn)賬金額變成20
用戶1轉(zhuǎn)賬金額變成-20
用戶2轉(zhuǎn)賬金額變成7
用戶3轉(zhuǎn)賬金額變成7

也就是說,amount被后面的線程修改了,但是前面線程還沒有執(zhí)行完。
用戶0應(yīng)該轉(zhuǎn)賬-7的,中間還沒有執(zhí)行完畢,結(jié)果被線程1修改了amount為20,用戶0繼續(xù)執(zhí)行轉(zhuǎn)賬,余額變成177. 其他依次推理。

amount這個變量被多個線程競爭修改了,這個就是程序的共享變量。

到底如何解決?

方法非常簡單:直接干掉共享變量。

下面就是消除共享變量的方法: 讓共享變成每個線程訪問獨立運行空間

所以代碼改動如下:

import random
import threading
import datetime
import time

xuewei = {'balance': 157}

lists = [-7, 20, -20, 7] ?# 4次轉(zhuǎn)賬的數(shù)額,負(fù)數(shù)為學(xué)委的賬戶轉(zhuǎn)出,正數(shù)為他人轉(zhuǎn)入。
# 我們不要依賴amount變量了
def transfer():
? ? name = threading.current_thread().getName()
? ? xuewei['balance'] += lists[int(name)] #通過線程名字來獲取對應(yīng)金額
? ? print("xuewei賬戶余額:", xuewei['balance'])

# 創(chuàng)建4個任務(wù)給學(xué)委轉(zhuǎn)賬上面lists的金額
threads = []
for i in range(4):
? ? amount = lists[i]
? ? name = str(i)
? ? print("%s 計劃轉(zhuǎn)賬 %s" % (name, amount))
? ? # mythread = threading.Thread(name=name, target=lambda: transfer())
? ? def event():
? ? ? ? transfer()
? ? mythread = threading.Thread(name=name, target=event)
? ? threads.append(mythread)

# 開始轉(zhuǎn)賬
for t in threads:
? ? t.start()

# 等待3秒讓上面的轉(zhuǎn)賬任務(wù)都完成,我們在看看賬戶余額
time.sleep(3)
print("-" * 16)
print("學(xué)委賬戶余額:", xuewei['balance'])

運行結(jié)果如下:

上面的代碼不管怎么運行,運行多少次最后學(xué)委的賬戶都是157.

這次展示的另一種方式來避開多線程出現(xiàn)bug的方法,使用一個list下標(biāo)跟線程名字一一對應(yīng),這樣只要是對應(yīng)名字的線程拿到的數(shù)值不錯錯亂。

到此這篇關(guān)于Python線程之如何解決共享變量問題的文章就介紹到這了,更多相關(guān)Python線程解決共享變量問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python實現(xiàn)定期檢查源目錄與備份目錄的差異并進(jìn)行備份功能示例

    Python實現(xiàn)定期檢查源目錄與備份目錄的差異并進(jìn)行備份功能示例

    這篇文章主要介紹了Python實現(xiàn)定期檢查源目錄與備份目錄的差異并進(jìn)行備份功能,涉及Python基于filecmp模塊的文件比較及讀寫等相關(guān)操作技巧,需要的朋友可以參考下
    2019-02-02
  • 如何使用pycharm連接Databricks的步驟詳解

    如何使用pycharm連接Databricks的步驟詳解

    這篇文章主要介紹了如何使用pycharm連接Databricks,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • Python簡單I/O操作示例

    Python簡單I/O操作示例

    這篇文章主要介紹了Python簡單I/O操作,結(jié)合實例形式分析了Python針對文件的I/O讀寫及cPickle模塊相關(guān)使用操作技巧,需要的朋友可以參考下
    2019-03-03
  • Python迭代和迭代器詳解

    Python迭代和迭代器詳解

    本篇文章主要介紹Python的迭代和迭代器,可迭代對象的相關(guān)概念,有需要的小伙伴可以參考下
    2016-11-11
  • pytorch動態(tài)神經(jīng)網(wǎng)絡(luò)(擬合)實現(xiàn)

    pytorch動態(tài)神經(jīng)網(wǎng)絡(luò)(擬合)實現(xiàn)

    這篇文章主要介紹了pytorch動態(tài)神經(jīng)網(wǎng)絡(luò)(擬合)實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 攻擊者是如何將PHP Phar包偽裝成圖像以繞過文件類型檢測的(推薦)

    攻擊者是如何將PHP Phar包偽裝成圖像以繞過文件類型檢測的(推薦)

    這篇文章主要介紹了攻擊者是如何將PHP Phar包偽裝成圖像以繞過文件類型檢測的,需要的朋友可以參考下
    2018-10-10
  • 五種Python轉(zhuǎn)義表示法

    五種Python轉(zhuǎn)義表示法

    這篇文章主要介紹了五種Python轉(zhuǎn)義表示法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Python數(shù)據(jù)分析基礎(chǔ)之異常值檢測和處理方式

    Python數(shù)據(jù)分析基礎(chǔ)之異常值檢測和處理方式

    這篇文章主要介紹了Python數(shù)據(jù)分析基礎(chǔ)之異常值檢測和處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • pygame+opencv實現(xiàn)讀取視頻幀的方法示例

    pygame+opencv實現(xiàn)讀取視頻幀的方法示例

    由于pygame.movie.Movie.play()只支持MPEG格式的視頻,所以決定使用與opencv讀取視頻幀的畫面,本文就詳細(xì)的介紹了pygame+opencv實現(xiàn)讀取視頻幀,感興趣的可以了解一下
    2021-12-12
  • 如何使用Python 打印各種三角形

    如何使用Python 打印各種三角形

    這篇文章主要介紹了如何使用Python 打印各種三角形,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-06-06

最新評論