因为多线程的时候,线程之间的数据共享,最大的危险是都可以来修改变量例如
import time ,threading balance = 0 def change_it(n): global balance balance = balance +n balance = balance - n def run_thread(n): for i in range(1000000): change_it(n) t1 = threading.Thread(target = run_thread , args = (5,)) t2 = threading.Thread(target = run_thread ,args = (8,)) t1.start() t2.start() t1.join() t2.join() print(balance)
共享变量balance初始化为0 ,先加后减理论上最后的数值应该是0 ,但是经过t1,t2多次运行后balance的结果就不一定是0
代码正常运行就像下边:
t1: x1 = balance + 5 # x1 = 0 + 5 = 5 t1: balance = x1 # balance = 5 t1: x1 = balance - 5 # x1 = 5 - 5 = 0 t1: balance = x1 # balance = 0 t2: x2 = balance + 8 # x2 = 0 + 8 = 8 t2: balance = x2 # balance = 8 t2: x2 = balance - 8 # x2 = 8 - 8 = 0 t2: balance = x2
# balance = 0
结果 balance = 0
那是因为 balance = balance + n 是先将balance +n的值存进临时变量,然后在将临时变量存入balance
类似于
x = balance + n
balance = x
所以在多次加减赋值之后因为多线程的变量共享导致变量的数据改变
例如:
t1: x1 = balance + 5 # x1 = 0 + 5 = 5 t2: x2 = balance + 8 # x2 = 0 + 8 = 8 t2: balance = x2 # balance = 8 t1: balance = x1 # balance = 5 t1: x1 = balance - 5 # x1 = 5 - 5 = 0 t1: balance = x1 # balance = 0 t2: x2 = balance - 8 # x2 = 0 - 8 = -8 t2: balance = x2 # balance = -8 结果 balance = -8
所以要保证数据的正确要加锁,保证在一个线程运算时,只能由一个线程去读写。
修改如下:
import time, threading lock = threading.Lock() balance = 0 def change_it(n): global balance balance = balance + n balance = balance - n def run_thread(n): for i in range(100000): lock.acquire() try: change_it(n) finally: lock.release() t1 = threading.Thread(target=run_thread, args=(5,)) t2 = threading.Thread(target=run_thread, args=(8,)) t1.start() t2.start() t1.join() t2.join() print(balance)
结果一直保持0
这样保证变量在调用时不会被其他的线程读写