多線程下的list


前言

listPython 常用的幾個基本數據類型之一.正常情況下我們會對 list 有增刪改查的操作,顯然易見不會有任何問題.那么如果我們試着在多線程下操作list 會有問題嗎?

多線程下的 list

安全 or 不安全? 不安全!

通常我們說的線程安全是指針對某個數據結構的所有操作都是線程安全,在這種定義下,Python 常用的數據結構 list,dict,str 等都是線程不安全的

盡管多線程下的 list 是線程不安全的,但是在 append 的操作下是它又是線程安全的.

如何判斷線程安全呢?

對於線程安全不安全,我們可以通過極端條件下去復現,從而得出結論。比如說判斷 list 是否線程安全

import threading
import time

# 隨意設置 count 的值,值越大錯誤拋出的越快
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)

有時候一次運行並不一定就會出錯,多次重試之后會出現類似下面的錯誤

很顯然這種操作方式不具有普適性,如果要是歐氣太強,說不定會一直不出現異常。

那么出了這種方式,有沒有比較簡單有效的方法嗎?答案是有的

dis

dis 庫是 Python 自帶的一個庫,可以用來分析字節碼。這里我們需要有這樣的認識,字節碼的每一行都是一個原子操作,多線程切換就是以原子操作為單位的,如果一個操作需要兩行字節碼就說明它是線程不安全的

remove

這里我們先看一下上面 listremove 操作

>>> 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

從上面不難看出,整個 remove 操作被分成了好幾條指令,這就意味着在多線程情況下會出現錯亂的情況,試想一下,如果多線程下都去 remove 列表的話,並且不按照順序,很容易出現問題。

append

在最上面我們說到,listappend 操作是線程安全的,那么究竟是為什么呢?我們同樣來用 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 也是有幾條指令,勢必在多線程執行的情況下也會發生交錯,但是對於多線程下我們操作 append, 我們肯定也不會在乎這個時候 list 到順序問題了,所以我們說它的 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM