【Python】 线程全局变量共享、同步

  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)

将部分代码修改:
在这里插入图片描述
不管哪个线程先执行,最终的结果是一样的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值