假如,開了十個線程並且做同樣的一件事,他們需要帶着自己的數據進來,完成事情后帶着自己的數據出去。如果是並發,同時進來,他們的數據就會混亂。
一般情況,我們加鎖就可以了,一個人先進來,先加鎖,另一個人過來看到加鎖了,就在外面等,等里面的人出來,自己進去加鎖,這樣就不會出現數據混亂的問題。
另一種解決方法就是threading.local()來解決問題。
先看下面這個現象
from threading import Thread ret = -1 # 先定義一個變量 def task(arg): # 寫個任務,加個參數 global ret # 聲明ret全局變量 ret = arg # 每一個線程進來到要改這個變量 print(ret) # 每個線程來,改了ret,然后取ret的值 for i in range(10): # i是線程的值,0 1 2 3 4 5 6 7 8 9 t = Thread(target=task, args=(i,)) # 開10個線程 t.start()
# 打印結果 0 1 2 3 4 5 6 7 8 9
這個程序開了10個線程,每個線程都執行了更改ret的值並獲取ret更改后的值,如果非常快,他們取到的值都不一樣.
如果讓他們睡兩秒再執行
from threading import Thread import time ret = -1 # 先定義一個變量 def task(arg): # 寫個任務,加個參數 global ret # 聲明ret全局變量 ret = arg # 每一個線程進來到要改這個變量 time.sleep(2) print(ret) # 每個線程來,改了ret,然后取ret的值 for i in range(10): # i是線程的值,0 1 2 3 4 5 6 7 8 9 t = Thread(target=task, args=(i,)) # 開10個線程 t.start()
# 打印結果 9 9 9 9 9 9 9 9 9 9
打印結果全是9
那么解決這個問題我們可以用threading.local()方法
from threading import Thread from threading import local import time # 這是一個特殊的對象 ret = local() # 先實例化一個對象 def task(arg): # 寫個任務,加個參數 ret = arg # 每一個線程進來都給他開辟一個獨立的空間 單純的threading.local()的作用就是這個 time.sleep(2) print(ret) # 每個線程來,改了ret,然后取ret的值 for i in range(10): # i是線程的值,0 1 2 3 4 5 6 7 8 9 t = Thread(target=task, args=(i,)) # 開10個線程 t.start()
# 打印結果 0 3 2 5 7 9 8 4 1 6
threading.local()的作用就是為每個線程開辟一個獨立的空間進行數據存儲。
接下來我們自定義local對象
from threading import get_ident,Thread import time storage = {} def set(k,v): # 來給storage設置值 ident = get_ident() # get_ident()能獲取唯一標識,是一組數字 if ident in storage: storage[ident][k] = v else: storage[ident] = {k:v} def get(k): # 來取storage的值 ident = get_ident() return storage[ident][k] def task(arg): set('val',arg) v = get('val') print(v) for i in range(10): t = Thread(target=task,args=(i,)) t.start()