詳解Python多線程下的list
list 是 Python 常用的幾個(gè)基本數(shù)據(jù)類型之一.正常情況下我們會(huì)對(duì) list 有增刪改查的操作,顯然易見(jiàn)不會(huì)有任何問(wèn)題.那么如果我們?cè)囍诙嗑€程下操作list 會(huì)有問(wèn)題嗎?
多線程下的 list
安全 or 不安全? 不安全!
通常我們說(shuō)的線程安全是指針對(duì)某個(gè)數(shù)據(jù)結(jié)構(gòu)的所有操作都是線程安全,在這種定義下,Python 常用的數(shù)據(jù)結(jié)構(gòu) list,dict,str 等都是線程不安全的
盡管多線程下的 list 是線程不安全的,但是在 append 的操作下是它又是線程安全的.
如何判斷線程安全呢?
對(duì)于線程安全不安全,我們可以通過(guò)極端條件下去復(fù)現(xiàn),從而得出結(jié)論。比如說(shuō)判斷 list 是否線程安全
import threading
import time
# 隨意設(shè)置 count 的值,值越大錯(cuò)誤拋出的越快
count = 1000
l = []
def add():
for i in range(count):
l.append(i)
time.sleep(0.0001)
def remove():
for i in range(count):
l.remove(i)
time.sleep(0.0001)
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=remove)
t1.start()
t2.start()
t1.join()
t2.join()
print(l)
有時(shí)候一次運(yùn)行并不一定就會(huì)出錯(cuò),多次重試之后會(huì)出現(xiàn)類似下面的錯(cuò)誤

很顯然這種操作方式不具有普適性,如果要是歐氣太強(qiáng),說(shuō)不定會(huì)一直不出現(xiàn)異常。
那么出了這種方式,有沒(méi)有比較簡(jiǎn)單有效的方法嗎?答案是有的
dis
dis 庫(kù)是 Python 自帶的一個(gè)庫(kù),可以用來(lái)分析字節(jié)碼。這里我們需要有這樣的認(rèn)識(shí),字節(jié)碼的每一行都是一個(gè)原子操作,多線程切換就是以原子操作為單位的,如果一個(gè)操作需要兩行字節(jié)碼就說(shuō)明它是線程不安全的
remove
這里我們先看一下上面 list 的 remove 操作
>>> import dis
>>> def test_remove():
... a = [1]
... a.remove(0)
...
>>> dis.dis(test_remove)
2 0 LOAD_CONST 1 (1)
2 BUILD_LIST 1
4 STORE_FAST 0 (a)
3 6 LOAD_FAST 0 (a)
8 LOAD_ATTR 0 (remove)
10 LOAD_CONST 2 (0)
12 CALL_FUNCTION 1
14 POP_TOP
16 LOAD_CONST 0 (None)
18 RETURN_VALUE
從上面不難看出,整個(gè) remove 操作被分成了好幾條指令,這就意味著在多線程情況下會(huì)出現(xiàn)錯(cuò)亂的情況,試想一下,如果多線程下都去 remove 列表的話,并且不按照順序,很容易出現(xiàn)問(wèn)題。
append
在最上面我們說(shuō)到,list 的 append 操作是線程安全的,那么究竟是為什么呢?我們同樣來(lái)用 dis 查看一下
8 19 LOAD_GLOBAL 0 (a)
22 LOAD_ATTR 2 (append)
25 LOAD_CONST 2 (1)
28 CALL_FUNCTION 1
31 POP_TOP
這里顯然,append 也是有幾條指令,勢(shì)必在多線程執(zhí)行的情況下也會(huì)發(fā)生交錯(cuò),但是對(duì)于多線程下我們操作 append, 我們肯定也不會(huì)在乎這個(gè)時(shí)候 list 到順序問(wèn)題了,所以我們說(shuō)它的 append 是線程安全的
參考
https://stackoverflow.com/questions/6319207/are-lists-thread-safe/19728536#19728536
https://docs.python.org/3/faq/library.html#what-kinds-of-global-value-mutation-are-thread-safe
以上就是詳解Python多線程下的list的詳細(xì)內(nèi)容,更多關(guān)于Python多線程下的list的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python獲取當(dāng)前文件路徑以及父文件路徑的方法
今天小編就為大家分享一篇python獲取當(dāng)前文件路徑以及父文件路徑的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
Python Celery異步任務(wù)隊(duì)列使用方法解析
這篇文章主要介紹了Python Celery異步任務(wù)隊(duì)列使用方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
python實(shí)現(xiàn)銀行賬戶系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)銀行賬戶系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02
python經(jīng)典練習(xí)百題之猴子吃桃三種解法
這篇文章主要給大家介紹了關(guān)于python經(jīng)典練習(xí)百題之猴子吃桃三種解法的相關(guān)資料, Python猴子吃桃子編程是一個(gè)趣味性十足的編程練習(xí),在這個(gè)練習(xí)中,我們將要使用Python語(yǔ)言來(lái)模擬一只猴子吃桃子的過(guò)程,需要的朋友可以參考下2023-10-10
python dict remove數(shù)組刪除(del,pop)
我們?cè)谟脭?shù)組列表做刪除的時(shí)候,可能選擇2個(gè)方法,一個(gè)是del,一個(gè)是pop方法2013-03-03
用python查找統(tǒng)一局域網(wǎng)下ip對(duì)應(yīng)的mac地址
這篇文章主要介紹了用python查找統(tǒng)一局域網(wǎng)下ip對(duì)應(yīng)的mac地址的示例代碼,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01

