1 import time
2 import threading
3
4 nums=[11,22]
5 def test1(temp):
6 temp.append(33)
7 print("全局的nums是%s" % str(temp))
8
9
10 def test2(temp):
11 print("全局的nums是%s" % str(temp))
12
13
14 def main():
15
16 # args中必须是一个元组,元组中添加一个问号就可以
17 t1=threading.Thread(target=test1,args=(nums,))
18 t2=threading.Thread(target=test2,args=(nums,))
19 t1.start()
20
21 time.sleep(1)
22 t2.start()
23 time.sleep(2)
24 print(nums)
25
26 if __name__ == "__main__":
27 main()
结果
在这里插入图片描述
共享全局变量带来的问题:
1 import time
2 import threading
3
4 num=0
5 def test1(temp):
6 global num
7 for i in range(temp):
8 num+=1
9 print(num)
10
11
12 def test2(temp):
13 global num
14 for i in range(temp):
15 num+=1
16 print(num)
17
18
19 def main():
20
21 # args中必须是一个元组,元组中添加一个问号就可以
22 t1=threading.Thread(target=test1,args=(100,))
23 t2=threading.Thread(target=test2,args=(100,))
24 t1.start()
25
26 t2.start()
27 time.sleep(2)
28
29 print("全局%d" % num)
30
31 if __name__ == "__main__":
32 main()
- 结果如下:
但是下边情况:
1 import time
2 import threading
3
4 num=0
5 def test1(temp):
6 global num
7 for i in range(temp):
8 num+=1
9 print(num)
10
11
12 def test2(temp):
13 global num
14 for i in range(temp):
15 num+=1
16 print(num)
17
18
19 def main():
20
21 # args中必须是一个元组,元组中添加一个问号就可以
22 t1=threading.Thread(target=test1,args=(1000001,))
23 t2=threading.Thread(target=test2,args=(1000000,))
24 t1.start()
25
26 t2.start()
27 time.sleep(2)
28
29 print("全局%d" % num)
30
31 if __name__ == "__main__":
main()
- 结果如下:
结果竟然不是2000000,不到2000000,
原因是因为操作系统在执行每一条代码的时候,会将一条代码翻译成很多条指令,而在执行这些指令的时候,因操作系统的调度问题,恰巧某些指令的时间片到了,将其加入等待队列,而去执行其他的指令,执行完回来继续执行方才时间片到的那条指令下边的指令时候,将原来别的指令修改的全局变量的值再次覆盖,从而导致一些指令执行了,但是效果没有显示出来,当执行的次数越多,恰巧发生某条代码的指令执行时候恰巧去执行别的代码的指令的机会越大,从而导致总的次数不到2000000,二十1500000左右。当执行的次数越多的时候,这个概越大,错误的机会越多,导致最后的数字越小。
资源竞争导致的!!!
解决办法:同步
# 创建锁
l=threading.Lock()
# 锁定
l.acquire()
# 解锁
l.release()
1 import time
2 import threading
3 # 默认是没有上锁的
4 lk=threading.Lock()
5 num=0
6 def test1(temp):
7 global num
8 lk.acquire()
9 # 如果之前没有被上锁,则上锁成功,
10 # 如果之前已经被被人上锁了,则阻塞
11 for i in range(temp):
12 num+=1
13 lk.release()
14 print(num)
15
16
17 def test2(temp):
18 global num
19 lk.acquire()
20 # 如果之前没有被上锁,则上锁成功,
21 # 如果之前已经被被人上锁了,则阻塞
22 for i in range(temp):
23 num+=1
24 lk.release()
25 print(num)
26
27
28 def main():
29
30 # args中必须是一个元组,元组中添加一个问号就可以
31 t1=threading.Thread(target=test1,args=(1000001,))
32 t2=threading.Thread(target=test2,args=(1000000,))
33 t1.start()
34
35 t2.start()
36 time.sleep(2)
37
38 print("全局%d" % num)
39
40 if __name__ == "__main__":
41 main()
结果:
1000001
2000001
全局2000001
加锁保证了全举变量不被任意修改
4 lk=threading.Lock()
5 num=0
6 def test1(temp):
7 global num
8 # 如果之前没有被上锁,则上锁成功,
9 # 如果之前已经被被人上锁了,则阻塞
10 for i in range(temp):
11 lk.acquire()
12 num+=1
13 lk.release()
14 print(num)
15
16
17 def test2(temp):
18 global num
19 # 如果之前没有被上锁,则上锁成功,
20 # 如果之前已经被被人上锁了,则阻塞
21 for i in range(temp):
22 lk.acquire()
23 num+=1
24 lk.release()
25 print(num)
将部分代码修改:
不管哪个线程先执行,最终的结果是一样的