執行緒資料不安全現象
阿新 • • 發佈:2020-07-26
執行緒資料不安全現象
from threading import Thread n = 0 def add(): for i in range(500000): global n n += 1 def sub(): for i in range(500000): global n n -= 1 t_l = [] for i in range(2): t1 = Thread(target=add) t1.start() t2 = Thread(target=sub) t2.start() t_l.append(t1) t_l.append(t2) for t in t_l: t.join() print(n) #結果n不為0
from threading import Thread import time n = [] def append(): for i in range(500000): n.append(1) def pop(): for i in range(500000): if not n: time.sleep(0.0000001) n.pop() t_l = [] for i in range(20): t1 = Thread(target=append) t1.start() t2 = Thread(target=pop) t2.start() t_l.append(t1) t_l.append(t2) for t in t_l: t.join() print(n) #使用append pop方法資料安全
+= -= *= /= while if 資料不安全 + 和 賦值是分開的兩個操作
append pop strip資料安全 列表中的方法或者字典中的方法去操作全域性變數的時候 資料安全的
執行緒之間也存在資料不安全
執行緒鎖
from threading import Thread,Lock n = 0 def add(lock): for i in range(500000): global n with lock: n += 1 def sub(lock): for i in range(500000): global n with lock: n -= 1 t_l = [] lock = Lock() for i in range(2): t1 = Thread(target=add,args=(lock,)) t1.start() t2 = Thread(target=sub,args=(lock,)) t2.start() t_l.append(t1) t_l.append(t2) for t in t_l: t.join() print(n)
from threading import Thread,Lock
import time
n = []
def append():
for i in range(500000):
n.append(1)
def pop(lock):
for i in range(500000):
with lock:
if not n:
time.sleep(0.0000001) # 強制CPU輪轉
n.pop()
t_l = []
lock = Lock()
for i in range(20):
t1 = Thread(target=append)
t1.start()
t2 = Thread(target=pop,args=(lock,))
t2.start()
t_l.append(t1)
t_l.append(t2)
for t in t_l:
t.join()
print(n)
不要操作全域性變數,不要在類裡操作靜態變數
+= -= *= /= if while 資料不安全
queue logging 資料安全的
單例模式
import time
class A:
from threading import Lock
__instance = None
lock = Lock()
def __new__(cls, *args, **kwargs):
with cls.lock:
if not cls.__instance:
time.sleep(0.000001) # cpu輪轉
cls.__instance = super().__new__(cls)
return cls.__instance
def func():
a = A()
print(a)
from threading import Thread
for i in range(10):
Thread(target=func).start()