欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python線程之認(rèn)識(shí)線程安全?

 更新時(shí)間:2022年02月24日 10:44:24   作者:雷學(xué)委  
這篇文章主要介紹了Python線程之認(rèn)識(shí)線程安全,線程安全,名字就非常直接,在多線程情況下是安全的,多線程操作上的安全,下面學(xué)習(xí)線程安全的文章詳細(xì)內(nèi)容,需要的小伙伴可以參考一下

一、什么是線程安全?

線程安全,名字就非常直接,在多線程情況下是安全的,多線程操作上的安全。

比如一個(gè)計(jì)算加法的函數(shù),不管是一千個(gè)還是一萬(wàn)個(gè)線程,我們希望它執(zhí)行的結(jié)果總是正確的,1+1 必須永遠(yuǎn)等于2, 而不是線程少的時(shí)候1+1 變成3或者4了。

通常我們都用線程安全來(lái)修飾一個(gè)類,修飾一個(gè)函數(shù):

我們會(huì)說(shuō)我設(shè)計(jì)的這個(gè)類是線程安全的
這意味著,在多線程環(huán)境下,同時(shí)調(diào)用這個(gè)類的函數(shù)不會(huì)出現(xiàn)函數(shù)設(shè)置預(yù)期之外的異常(上述的1+1=3的情況)

二、在Python中有哪些類是線程安全的?

dict 和 list,tuple這些都是線程安全。

它們是被全局解釋器保障了,這個(gè)鎖:GIL(全局解釋器鎖)確保了任何時(shí)候只能有一個(gè)線程執(zhí)行相應(yīng)操作的字節(jié)碼。參考

但是這番話也是說(shuō)的不清不楚的。

現(xiàn)在我們拿轉(zhuǎn)賬來(lái)解析吧:

xuewei_account = dict()
xuewei_account['amount'] = 100

# amount為負(fù)數(shù)即是轉(zhuǎn)出金額
def transfer(money):
    xuewei_account['amount'] +=  money

如上,代碼為一個(gè)函數(shù)對(duì)jb_account(賬戶)進(jìn)行轉(zhuǎn)入金額操作。

這里用了dict類型,GIL會(huì)保證只有一個(gè)線程操作賬戶。

下面是多個(gè)線程進(jìn)行操作的代碼:

import random
import threading
import datetime
import time

xuewei_account = dict()
xuewei_account['amount'] = 100


# amount為負(fù)數(shù)即是轉(zhuǎn)出金額
def transfer(money):
    xuewei_account['amount'] +=  money


# 創(chuàng)建4個(gè)任務(wù)給重復(fù)學(xué)委賬戶轉(zhuǎn)賬
threads = []
for i in range(200):
    t1 = threading.Thread(target=lambda: transfer(-1))
    threads.append(t1)
    t2 = threading.Thread(target=lambda: transfer(1))
    threads.append(t2)

for t in threads:
    t.start()
    
# 這次不用sleep了,用join來(lái)等待所有線程執(zhí)行完畢
# join函數(shù)必須線程start后才能調(diào)用,否則出錯(cuò)。
for t in threads:
    t.join()

print("-" * 16)
print("活躍線程數(shù):", threading.active_count())
print("活躍線程:", threading.current_thread().name)
print("學(xué)委賬戶余額:", xuewei_account)

這段代碼運(yùn)行的輸出結(jié)果正常,因?yàn)槭欠磸?fù)+1/-1,最后肯定是恢復(fù)原賬戶余額。

雖然多個(gè)線程,但是每個(gè)線程只對(duì)xuewei_account進(jìn)行一次讀寫,這時(shí)候dict是安全的。

但是我們把賦值修改dict的操作變多之后(特別是一個(gè)線程內(nèi)反復(fù)多次獲取值然后修改),像下面的代碼:

import random
import threading
import datetime
import time

xuewei_account = dict()
xuewei_account['amount'] = 100


# amount為負(fù)數(shù)即是轉(zhuǎn)出金額
def transfer(money):
? ? for i in range(100000):
? ? ? ? xuewei_account['amount'] = xuewei_account['amount'] + money


# 創(chuàng)建400個(gè)任務(wù)重復(fù)給學(xué)委賬戶轉(zhuǎn)賬
threads = []
for i in range(200):
? ? t1 = threading.Thread(target=lambda: transfer(-1))
? ? threads.append(t1)
? ? t2 = threading.Thread(target=lambda: transfer(1))
? ? threads.append(t2)

for t in threads:
? ? t.start()
for t in threads:
? ? t.join()

print("-" * 16)
print("活躍線程數(shù):", threading.active_count())
print("活躍線程:", threading.current_thread().name)
print("學(xué)委賬戶余額:", xuewei_account)

這是某一次運(yùn)行結(jié)果(不保證每次acount的數(shù)值一樣):

我們看到dict還是扛不住多個(gè)線程反復(fù)的寫操作。

這里區(qū)別是:每個(gè)線程只對(duì)xuewei_account進(jìn)行大量讀寫,雖然dict是安全的,但是多個(gè)線程中間穿插修改了account,程序方法棧出現(xiàn)操作到舊值(看下面的圖)。

主要是下面這段代碼:

xuewei_account[‘a(chǎn)mount'] += money 
# 即是 xuewei_account[‘a(chǎn)mount'] = xuewei_account[‘a(chǎn)mount']+ money

再一步抽象簡(jiǎn)化可以寫成:

a = a + b

每個(gè)線程都執(zhí)行 +b 操作,最后a的值應(yīng)該是a+2b。

上面的操作意味這下面的情況發(fā)生了:

在某個(gè)線程中可能出現(xiàn)某一個(gè)線程T1獲取了a值 ,準(zhǔn)備加上b。

另外一個(gè)線程T2已經(jīng)完成了a+b操作,把a(bǔ)的值變成了a+b了。

但是接下來(lái)T1 拿了a的值再執(zhí)行a+b操作,把a(bǔ)的值變成a+b。

這樣就少加了一個(gè)b,本來(lái)最后結(jié)果是a+2b 的變成了 a+b(因?yàn)門1拿了a的舊值,中間T2執(zhí)行完,T1才繼續(xù)執(zhí)行)

當(dāng)然實(shí)際多線程之間交互比上圖還要隨機(jī)。

三、如何做到真正線程安全?

dict讀取數(shù)據(jù)是線程安全,但是被反復(fù)讀寫就容易出現(xiàn)數(shù)據(jù)混亂。

如果我們要設(shè)計(jì)一個(gè)線程安全的函數(shù),那么它必須不涉及任何共享變量或者是完全沒(méi)有狀態(tài)依賴的函數(shù)

def thread_safe_method():
? ? pass

1.無(wú)狀態(tài)函數(shù)

比如下面的加法函數(shù),不管多少個(gè)線程調(diào)用,返回值永遠(yuǎn)是預(yù)期的a+b。

def add(a, b):
? ? return a + b

2.另一種 化繁為簡(jiǎn)

許我們可以把多線程轉(zhuǎn)換為單線程,這個(gè)需要一個(gè)線程安全的媒介。

到此這篇關(guān)于Python線程之認(rèn)識(shí)線程安全 的文章就介紹到這了,更多相關(guān)認(rèn)識(shí)Python線程安全 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python計(jì)算一個(gè)序列的平均值的方法

    python計(jì)算一個(gè)序列的平均值的方法

    這篇文章主要介紹了python計(jì)算一個(gè)序列的平均值的方法,涉及Python遞歸遍歷與數(shù)學(xué)計(jì)算的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • Django REST framework 限流功能的使用

    Django REST framework 限流功能的使用

    DRF常用功能的案例基本用法都有講解,關(guān)于限流(Throttling)這個(gè)功能其實(shí)在真實(shí)的業(yè)務(wù)場(chǎng)景中能真正用到的其實(shí)不算多。今天說(shuō)這個(gè)話題其實(shí)一方面是討論功能,另一方面也是希望換個(gè)角度去審視我們的開(kāi)發(fā)過(guò)程,希望大家可以在使用DRF功能的同時(shí),也了解一下功能背后的實(shí)現(xiàn)
    2021-06-06
  • Python創(chuàng)建模塊及模塊導(dǎo)入的方法

    Python創(chuàng)建模塊及模塊導(dǎo)入的方法

    這篇文章主要介紹了Python創(chuàng)建模塊及模塊導(dǎo)入的方法,實(shí)例分析了模塊的定義、導(dǎo)入及模塊屬性的使用技巧,并附帶說(shuō)明了包的概念與用法,需要的朋友可以參考下
    2015-05-05
  • Python實(shí)用技巧之列表、字典、集合中根據(jù)條件篩選數(shù)據(jù)詳解

    Python實(shí)用技巧之列表、字典、集合中根據(jù)條件篩選數(shù)據(jù)詳解

    這篇文章主要給大家介紹了關(guān)于Python技巧之在列表、字典、集合中根據(jù)條件篩選數(shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧
    2018-07-07
  • Python解析Laravel?Cookie技巧示例

    Python解析Laravel?Cookie技巧示例

    本文將介紹如何使用Python解析Laravel Cookie,以便在Web開(kāi)發(fā)中處理這些Cookie數(shù)據(jù),我們將深入了解Cookie的結(jié)構(gòu),以及如何在Python中對(duì)其進(jìn)行解析和操作
    2023-12-12
  • python beautiful soup庫(kù)入門安裝教程

    python beautiful soup庫(kù)入門安裝教程

    Beautiful Soup是python的一個(gè)庫(kù),最主要的功能是從網(wǎng)頁(yè)抓取數(shù)據(jù)。今天通過(guò)本文給大家分享python beautiful soup庫(kù)入門教程,需要的朋友參考下吧
    2021-08-08
  • Python交換字典鍵值對(duì)的四種方法實(shí)例

    Python交換字典鍵值對(duì)的四種方法實(shí)例

    字典中有成對(duì)出現(xiàn)的鍵和值,但是字典中的鍵值對(duì)不是都能修改的,只有值才能修改,下面這篇文章主要給大家介紹了關(guān)于Python交換字典鍵值對(duì)的四種方法,需要的朋友可以參考下
    2022-12-12
  • 對(duì)Python w和w+權(quán)限的區(qū)別詳解

    對(duì)Python w和w+權(quán)限的區(qū)別詳解

    今天小編就為大家分享一篇對(duì)Python w和w+權(quán)限的區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • anaconda中Conda創(chuàng)建虛擬環(huán)境的實(shí)現(xiàn)步驟

    anaconda中Conda創(chuàng)建虛擬環(huán)境的實(shí)現(xiàn)步驟

    在Anaconda中,可以使用conda命令來(lái)創(chuàng)建和管理虛擬環(huán)境,本文主要介紹了anaconda中Conda創(chuàng)建虛擬環(huán)境的實(shí)現(xiàn)步驟,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • python-opencv-cv2.threshold()二值化函數(shù)的使用

    python-opencv-cv2.threshold()二值化函數(shù)的使用

    這篇文章主要介紹了python-opencv-cv2.threshold()二值化函數(shù)的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評(píng)論