为全局变量赋值_关于多线程使用全局变量的问题

2dac7d86ff3da46725c6c5c69e5c6bc6.gif

在多线程中,如果多线程同时对一个全局变量进行操作时,就有可能出现异常,比如下面的程序:

# -*- coding:UTF-8 -*-import threadingimport time#定义一个全局变量g_num = 0def test1(num):    global g_num    for i in range(num):        g_num += 1    print(g_num)def test2(num):    global g_num    for i in range(num):        g_num += 1    print(g_num)def main():    t1 = threading.Thread(target=test1,args=(10000000,))    t2 = threading.Thread(target=test2,args=(10000000,))    t1.start()    t2.start()    time.sleep(5)    print('结束:',g_num)if __name__ == '__main__':    main()

运行后得到的结果本应是20000000,可是结果真是这样吗?运行后得到的结果是:

bb1d24bcaff633691a4e678342244f3b.png

这是因为一个程序在未运行完全时就被休眠而执行另一个程序了,从而导致这样的结果。说明多个线程同时对一个全局变量进行操作,会出现资源竞争问题,从而数据结果会不正确,导致线程安全问题。简单来说:

  1. 在g_num=0时,t1取得g_num=0。此时系统把t1调度为”sleeping”状态,把t2转换为”running”状态,t2也获得g_num=0

  2. 然后t2对得到的值进行加1并赋给g_num,使得g_num=1

  3. 然后系统又把t2调度为”sleeping”,把t1转为”running”。线程t1又把它之前得到的0加1后赋值给g_num。

  4. 这样导致虽然t1和t2都对g_num加1,但结果仍然是g_num=1

那么怎么解决这个问题呢?这里就用到了多线程的互斥锁。具体参见下面的程序:

# -*- coding:UTF-8 -*-import threadingimport time#定义一个全局变量g_num = 0def test1(num):    global g_num    #上锁    mutex.acquire()    for i in range(num):        g_num += 1    #解锁    mutex.release()    print(g_num)def test2(num):    global g_num    # 上锁    mutex.acquire()    for i in range(num):        g_num += 1    mutex.release()    print(g_num)def main():    t1 = threading.Thread(target=test1,args=(10000000,))    t2 = threading.Thread(target=test2,args=(10000000,))    t1.start()    t2.start()    time.sleep(3)    print('结束:',g_num)if __name__ == '__main__':    mutex = threading.Lock()    main()

互斥锁

当多个线程几乎同时修改共享数据时,需要进行同步控制

线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制就是引入互斥锁。

互斥锁为我们的资源引入一个状态:锁定/非锁定

某个线程要更改共享数据时,先将其锁定,此时,资源的状态为锁定,其他线程不能对其更改;

直到该线程释放资源,资源状态变为非锁定状态,其他线程才能再次锁定该资源。

互斥锁,保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

在threading模块里,定义了Lock()类,可以方便的处理锁定。

此时我们就可以得到我们想要的答案了:a716a8477082b72ba4dde7dafed6f0d6.png

END

65e698e8889fdd1a2ad655d2e8a6aa9a.png


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值