python进阶之多线程对同一个全局变量的处理方法


Posted in Python onNovember 09, 2018

通常情况下:

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 相关文章推荐
Python 字符串大小写转换的简单实例
Jan 21 Python
python实现装饰器、描述符
Feb 28 Python
在python中安装basemap的教程
Sep 20 Python
JSON文件及Python对JSON文件的读写操作
Oct 07 Python
浅谈python的dataframe与series的创建方法
Nov 12 Python
Python入门Anaconda和Pycharm的安装和配置详解
Jul 16 Python
Python Django 页面上展示固定的页码数实现代码
Aug 21 Python
将数据集制作成VOC数据集格式的实例
Feb 17 Python
Jupyter Notebook输出矢量图实例
Apr 14 Python
解决Tensorflow2.0 tf.keras.Model.load_weights() 报错处理问题
Jun 12 Python
python函数指定默认值的实例讲解
Mar 29 Python
5个pandas调用函数的方法让数据处理更加灵活自如
Apr 24 Python
python 多线程将大文件分开下载后在合并的实例
Nov 09 #Python
python 利用for循环 保存多个图像或者文件的实例
Nov 09 #Python
浅谈python写入大量文件的问题
Nov 09 #Python
启动Atom并运行python文件的步骤
Nov 09 #Python
Python产生Gnuplot绘图数据的方法
Nov 09 #Python
python pyheatmap包绘制热力图
Nov 09 #Python
Django 视图层(view)的使用
Nov 09 #Python
You might like
The specified CGI application misbehaved by not returning a complete set of HTTP headers
2011/03/31 PHP
PHP设计模式之装饰者模式
2012/02/29 PHP
PHP去掉json字符串中的反斜杠\及去掉双引号前的反斜杠
2015/09/30 PHP
学习php设计模式 php实现装饰器模式(decorator)
2015/12/07 PHP
thinkPHP模板中函数的使用方法示例
2016/11/30 PHP
php计算给定日期所在周的开始日期和结束日期示例
2017/02/06 PHP
PHP策略模式定义与用法示例
2017/07/27 PHP
php对微信支付回调处理的方法
2018/08/23 PHP
Javascript 类与静态类的实现(续)
2010/04/02 Javascript
JavaScript高级程序设计 DOM学习笔记
2011/09/10 Javascript
JAVASCRIPT车架号识别/验证函数代码 汽车车架号验证程序
2012/01/08 Javascript
html5 canvas js(数字时钟)实例代码
2013/12/23 Javascript
javascript实现倒计时N秒后网页自动跳转代码
2014/12/11 Javascript
JavaScript动态加载样式表的方法
2015/03/21 Javascript
jQuery中$(function() {});问题详解
2015/08/10 Javascript
深入理解(function(){... })();
2016/08/16 Javascript
js记录点击某个按钮的次数-刷新次数为初始状态的实例
2017/02/15 Javascript
react.js 父子组件数据绑定实时通讯的示例代码
2017/09/25 Javascript
NodeJS爬虫实例之糗事百科
2017/12/14 NodeJs
微信小程序scroll-view横向滑动嵌套for循环的示例代码
2018/09/20 Javascript
在Python中使用第三方模块的教程
2015/04/27 Python
Python使用shelve模块实现简单数据存储的方法
2015/05/20 Python
python如何获取当前文件夹下所有文件名详解
2019/01/25 Python
pytorch对梯度进行可视化进行梯度检查教程
2020/02/04 Python
pytorch数据预处理错误的解决
2020/02/20 Python
Top Villas美国:豪华别墅出租和度假屋
2018/07/10 全球购物
Wedgwood英国官方网站:英式精致骨瓷餐具、礼品与生活精品,源于1759年
2019/09/02 全球购物
英文自荐信
2013/12/19 职场文书
3.12植树节活动总结2014
2014/03/13 职场文书
学雷锋志愿者活动总结
2014/06/27 职场文书
四风自我剖析材料
2014/09/30 职场文书
幼儿园感恩节活动方案
2014/10/06 职场文书
群众路线剖析材料范文
2014/10/09 职场文书
施工现场安全管理制度
2015/08/05 职场文书
《牧场之国》教学反思
2016/02/22 职场文书
标准发言稿结尾
2019/07/18 职场文书