通常情况下:
from threading import Thread
global_num = 0
def func1():
global global_num
for i in range(1000000):
global_num += 1
print('---------func1:global_num=%s--------'%global_num)
def func2():
global global_num
for i in range(1000000):
global_num += 1
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)
lock = Lock()
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
输出结果:
global_num=0 ---------func1:global_num=1492752-------- --------fun2:global_num=1515462
#由于多线程不像多进程一样,每一个进程都一个独立的资源块,线程之间是共享主线程的一个资源块(虽然这样说不合适)
#这样虽然方便了线程之间的数据传递,但是又会由于线程之间执行顺序的不确定,导致最后的结果不是应该输出的正确结果。
#例如下面的例程,如果没有添加global_flag标志全局变量,就会出现,虽然逻辑上最后的结果是2000000(之所以选择这么大的一个数,是因为可以更明显的看出#这个问题),
#但是实际上并不是这个结果,而是一个小于2000000的结果,但是不排出偶然会出现2000000,这是一个极为理想的结果,这是为什么呢?
#主要还是由于线程被cpu调用的顺序不确定。具体来讲就是当主线程创建出两个子线程,分别是t1和t2,他们有分别指向func1()和func2()。
#在这两个线程中的函数中,都有一句“global_num += 1”,在计算机内部cpu执行时,这一条语句实际上是两个过程:第一个过程是从内存中读取global_num的值,完成加一操作,这个时候global_num的值还是原来的值;第二个过程是将求和的值付给global_num,这时候global_num的值才会更新。在程序执行过程中会出现这种
#情况:当cpu在执行线程t1中的语句到求和那条语句时,在执行完第一个过程停了下来,将线程t1抛出,转而执行线程t2,当线程执行一段时间后也出现这中情况
#有转而执行线程t1,这时,正好执行求和语句的第二个过程,完成最初的赋值,那么这一段时间内的整个求和就等于没做,所以出现这中最后结果不是2000000的##情况
#解决这种情况可以利用添加一个变量,利用“轮询”的方式执行,但是这样做的效率很低,而且还浪费cpu,所以一般采用“通知”方式来做。
轮询方式:
from threading import Thread
global_num = 0
global_flag = 0
def func1():
global global_num
global global_flag
if global_flag == 0:
for i in range(1000000):
global_num += 1
global_flag = 1
print('---------func1:global_num=%s--------'%global_num)
def func2():
global global_num
while True:
if global_flag != 0:
for i in range(1000000):
global_num += 1
break
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
运行结果:
global_num=0 ---------func1:global_num=1000000-------- --------fun2:global_num=2000000
通知方式:
from threading import Thread,Lock
global_num = 0
def func1():
global global_num
for i in range(1000000):
lock.acquire()#两个线程会最开始抢这个锁,拿到锁就会处于关锁,执行后面的程序,其他线程执行处于监听状态,等待这个线程开锁,再抢锁
global_num += 1
lock.release()
print('---------func1:global_num=%s--------'%global_num)
def func2():
global global_num
for i in range(1000000):
lock.acquire()
global_num += 1
lock.release()
print('--------fun2:global_num=%s'%global_num)
print('global_num=%s'%global_num)
lock = Lock()
t1 = Thread(target=func1)
t1.start()
t2 = Thread(target=func2)
t2.start()
输出结果:
global_num=0 ---------func1:global_num=1901175-------- --------fun2:global_num=2000000
以上这篇python进阶之多线程对同一个全局变量的处理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
python,多线程,全局变量
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。