Python线程之如何解决共享变量问题
前面提到了银行转账这个场景,展示了一个比较耗时的转账操作。
这篇继续转帐,下面展示一段程序,多个线程的操作都更改了amount
变量导致运行结果不对的问题。
前文说了转账问题
下面展示另一种转账的方式:
import random import threading import datetime import time xuewei = {'balance': 157} # amount为负数即是转出金额 def transfer(money): name = threading.current_thread().getName() print("%s 给xuewei转账 %s " % (name, money)) xuewei['balance'] += money print("xuewei账户余额:", xuewei['balance']) lists = [-7, 20, -20, 7] # 4次转账的数额,负数为学委的账户转出,正数为他人转入。 # 创建4个任务给学委转账上面lists的金额 threads = [] for i in range(4): amount = lists[i] name = "t-" + str(i) print("%s 计划转账 %s" % (name, amount)) mythread = threading.Thread(name=name, target=lambda: transfer(amount)) threads.append(mythread) # 开始转账 for t in threads: t.start() # 等待3秒让上面的转账任务都完成,我们在看看账户余额 time.sleep(3) print("-" * 16) print("学委账户余额:", xuewei['balance'])
这里启动了4个线程,每个线程内有个lambda
表达式,分别于学委的账户进行转账,但是最后结果是185. 而不是157.
下面是运行结果:
PS: 这只是一种运行结果。多线程的运行结果不是永远一样的。
如何解决这个问题?
观测结果我们发先amount
只保留了最后一个值。
好,下面改造一下:
import random import threading import datetime import time xuewei = {'balance': 157} lists = [-7, 20, -20, 7] # 4次转账的数额,负数为学委的账户转出,正数为他人转入。 def transfer(amount): name = threading.current_thread().getName() print("%s 给xuewei转账 %s " % (name,amount)) xuewei['balance'] += amount print("xuewei账户余额:", xuewei['balance']) # 创建4个任务给学委转账上面lists的金额 for i in range(4): amount = lists[i] name = str(i) # mythread = threading.Thread(name=name, target=lambda: transfer(amount)) def event(): print("%s 计划转账 %s" % (name, amount)) transfer(amount) mythread = threading.Thread(name=name, target=event) mythread.start() # 等待3秒让上面的转账任务都完成,我们在看看账户余额 time.sleep(3) print("-" * 16) print("学委账户余额:", xuewei['balance'])
学委这里加了一个event
函数,把转账计划打印出来。
从下面的一次运行结果看,event函数的输出结果没错,所有”计划转账“金额都如预期[-7, 20, -20 7]。 问题是transfer函数再多线程执行的时候,我们发现amount被多线程竞争修改了:
用户0转账金额变成20
用户1转账金额变成-20
用户2转账金额变成7
用户3转账金额变成7
也就是说,amount
被后面的线程修改了,但是前面线程还没有执行完。
用户0应该转账-7的,中间还没有执行完毕,结果被线程1修改了amount为20,用户0继续执行转账,余额变成177. 其他依次推理。
amount
这个变量被多个线程竞争修改了,这个就是程序的共享变量。
到底如何解决?
方法非常简单:直接干掉共享变量。
下面就是消除共享变量的方法: 让共享变成每个线程访问独立运行空间
所以代码改动如下:
import random import threading import datetime import time xuewei = {'balance': 157} lists = [-7, 20, -20, 7] # 4次转账的数额,负数为学委的账户转出,正数为他人转入。 # 我们不要依赖amount变量了 def transfer(): name = threading.current_thread().getName() xuewei['balance'] += lists[int(name)] #通过线程名字来获取对应金额 print("xuewei账户余额:", xuewei['balance']) # 创建4个任务给学委转账上面lists的金额 threads = [] for i in range(4): amount = lists[i] name = str(i) print("%s 计划转账 %s" % (name, amount)) # mythread = threading.Thread(name=name, target=lambda: transfer()) def event(): transfer() mythread = threading.Thread(name=name, target=event) threads.append(mythread) # 开始转账 for t in threads: t.start() # 等待3秒让上面的转账任务都完成,我们在看看账户余额 time.sleep(3) print("-" * 16) print("学委账户余额:", xuewei['balance'])
运行结果如下:
上面的代码不管怎么运行,运行多少次最后学委的账户都是157.
这次展示的另一种方式来避开多线程出现bug的方法,使用一个list下标跟线程名字一一对应,这样只要是对应名字的线程拿到的数值不错错乱。
到此这篇关于Python线程之如何解决共享变量问题的文章就介绍到这了,更多相关Python线程解决共享变量问题内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
原文出处:https://levin.blog.csdn.net/article/details/121965391
相关文章
- 这篇文章主要介绍了python-opencv-画外接矩形框的实例代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-09-04
C# WinForm多线程解决界面卡死问题的完美解决方案,使用BeginInvoke
问题描述:当我们的界面需要在程序运行中不断更新数据时,当一个textbox的数据需要变化时,为了让程序执行中不出现界面卡死的现像,最好的方法就是多线程来解决一个主线程来创建界...2020-06-24- 下面本文章来给大家介绍在php中成员变量的一些对比了,文章举了四个例子在这例子中分别对不同成员变量进行测试与获取操作,下面一起来看看。 有如下4个代码示例,你认...2016-11-25
Python astype(np.float)函数使用方法解析
这篇文章主要介绍了Python astype(np.float)函数使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-06-08- 2022虎年新年即将来临,小编为大家带来了一个利用Python编写的虎年烟花特效,堪称全网最绚烂,文中的示例代码简洁易懂,感兴趣的同学可以动手试一试...2022-02-14
- 在本篇文章里小编给大家分享的是一篇关于python中numpy.empty()函数实例讲解内容,对此有兴趣的朋友们可以学习下。...2021-02-06
python-for x in range的用法(注意要点、细节)
这篇文章主要介绍了python-for x in range的用法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-10- 这篇文章主要介绍了Python 图片转数组,二进制互转操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
- 这篇文章主要介绍了Python中的imread()函数用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-16
- 这篇文章主要介绍了python如何实现b站直播自动发送弹幕,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下...2021-02-20
- 本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
- 这篇文章主要介绍了R语言删除指定变量或对象的操作方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-05-06
- 今天小编就为大家分享一篇关于C#开启线程的四种方式示例详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...2020-06-25
- 这篇文章主要介绍了C#停止线程的方法,实例分析了C#正确停止线程的实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
python Matplotlib基础--如何添加文本和标注
这篇文章主要介绍了python Matplotlib基础--如何添加文本和标注,帮助大家更好的利用Matplotlib绘制图表,感兴趣的朋友可以了解下...2021-01-26- 这篇文章主要介绍了解决python 使用openpyxl读写大文件的坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-13
- 今天小编就为大家分享一篇python 计算方位角实例(根据两点的坐标计算),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-27
- 这篇文章主要为大家详细介绍了python实现双色球随机选号,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-05-02
- 在本篇文章里小编给大家整理的是一篇关于python中使用np.delete()的实例方法,对此有兴趣的朋友们可以学习参考下。...2021-02-01
- 这篇文章主要介绍了使用Python的pencolor函数实现渐变色功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-09