04-多线程共享全局变量的问题
问题
我们运行下面这段代码
1 import threading 2 3 4 num1 = 0 5 6 def test01(num): 7 for i in range(num): 8 global num1 9 num1 += 1 10 print("test01---------->" + str(num1)) 11 12 13 def test02(num): 14 for i in range(num): 15 global num1 16 num1 += 1 17 print("test02---------->" + str(num1)) 18 19 20 def main(): 21 t1 = threading.Thread(target = test01, args = (100000, )) # 创建一个对象 22 t2 = threading.Thread(target = test01, args = (100000, )) # 创建一个对象 23 24 # 创建子线程 25 t1.start() 26 t2.start() 27 print(num1) 28 29 if __name__ == "__main__": 30 main()
运行结果如下图所示:
原因
我们发现多次运行结果并不相同,下面就解释一下原因
CPU在执行代码的时候是一句一句执行的,我们创建了两个子线程;
这两个线程互相切换,一会儿执行线程t1,一会儿执行线程t2。CPU在执行这些线程中的代码的时候也是一句一句进行执行的。
假如代码在执行线程t1的时候,执行完了global num1和num1 + 1但是没有执行赋值语句,紧接着就去执行线程t2,线程t2在执行的时候也是执行了和线程t1一样的这两句代码,然后CPU在执行线程t1的赋值语句,此时num1的值为1。CPU执行完t1中的赋值语句之后在去执行t2中的赋值语句,执行完t2的赋值语句之后num1的值仍然是1。
解决办法
咱们可以使用上锁的方式来解决这个问题,即线程A在执行的时候不让线程2执行,等到线程1执行完成,再让线程2执行。
具体实现代码如下:
1 import time 2 import threading 3 4 5 num1 = 0 6 7 def test01(num): 8 for i in range(num): 9 mutex.acquire() # 上锁 10 global num1 11 num1 += 1 12 mutex.release() # 解锁 13 print("test01---------->" + str(num1)) 14 15 16 def test02(num): 17 for i in range(num): 18 mutex.acquire() # 上锁 19 global num1 20 num1 += 1 21 mutex.release() # 解锁 22 print("test02---------->" + str(num1)) 23 24 25 mutex = threading.Lock() 26 27 28 def main(): 29 t1 = threading.Thread(target = test01, args = (100000, )) # 创建一个对象 30 t2 = threading.Thread(target = test01, args = (100000, )) # 创建一个对象 31 32 # 创建子线程 33 t1.start() 34 t2.start() 35 time.sleep(0.1) 36 print(num1) 37 38 if __name__ == "__main__": 39 main()