@author jackzhenguo @desc @date 2019/10/28
122 多线程变量竞争引起的问题
只要弄明白问题暴露的原因,叫问题出现还是不困难的。
想象数据库的写入操作,一般需要耗费我们可以感知的时间。
为了模拟这个写入动作,简化期间,我们只需要延长修改变量a的时间,问题很容易就会还原出来。
import threading import time a = 0 def add1(): global a tmp = a + 1 time.sleep(0.2) # 延时0.2秒,模拟写入所需时间 a = tmp print('%s adds a to 1: %d'%(threading.current_thread().getName(),a)) threads = [threading.Thread(name='t%d'%(i,),target=add1) for i in range(10)] [t.start() for t in threads]
重新运行代码,只需一次,问题立马完全暴露,结果如下:
t0 adds a to 1: 1 t1 adds a to 1: 1 t2 adds a to 1: 1 t3 adds a to 1: 1 t4 adds a to 1: 1 t5 adds a to 1: 1 t7 adds a to 1: 1 t6 adds a to 1: 1 t8 adds a to 1: 1 t9 adds a to 1: 1
看到,10个线程全部运行后,a的值只相当于一个线程执行的结果。
下面分析,为什么会出现上面的结果:
这是一个很有说服力的例子,因为在修改a前,有0.2秒的休眠时间,某个线程延时后,CPU立即分配计算资源给其他线程。直到分配给所有线程后,根据结果反映出,0.2秒的休眠时长还没耗尽,这样每个线程get到的a值都是0,所以才出现上面的结果。
以上最核心的三行代码:
tmp = a + 1 time.sleep(0.2) # 延时0.2秒,模拟写入所需时间 a = tmp