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 help()函数用法详解
Mar 11 Python
Python编程中用close()方法关闭文件的教程
May 24 Python
python并发编程之多进程、多线程、异步和协程详解
Oct 28 Python
flask的orm框架SQLAlchemy查询实现解析
Dec 12 Python
PyTorch中 tensor.detach() 和 tensor.data 的区别详解
Jan 06 Python
基于matplotlib xticks用法详解
Apr 16 Python
python实现人像动漫化的示例代码
May 17 Python
Python Selenium实现无可视化界面过程解析
Aug 25 Python
如何实现一个python函数装饰器(Decorator)
Oct 12 Python
python按照list中字典的某key去重的示例代码
Oct 13 Python
关于Python不换行输出和不换行输出end=““不显示的问题(亲测已解决)
Oct 27 Python
python工具快速为音视频自动生成字幕(使用说明)
Jan 27 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
解析php中var_dump,var_export,print_r三个函数的区别
2013/06/21 PHP
php对包含html标签的字符串进行截取的函数分享
2014/06/19 PHP
PHP伪静态Rewrite设置之APACHE篇
2014/07/30 PHP
javascript 写类方式之五
2009/07/05 Javascript
Javascript 获取滚动条位置等信息的函数
2009/09/08 Javascript
jQuery.Autocomplete实现自动完成功能(详解)
2010/07/13 Javascript
JavaScript验证18位身份证号码最后一位正确性的实现代码
2014/08/07 Javascript
Javascript对象Clone实例分析
2015/06/09 Javascript
轻松学习jQuery插件EasyUI EasyUI创建菜单与按钮
2015/11/30 Javascript
基于javascript实现图片预加载
2016/01/05 Javascript
jQuery实现的倒计时效果实例小结
2016/04/16 Javascript
jQuery判断元素是否显示 是否隐藏的简单实现代码
2016/05/19 Javascript
leaflet的开发入门教程
2016/11/17 Javascript
JS判断是否为JSON对象及是否存在某字段的方法(推荐)
2016/11/29 Javascript
JavaScript中数组常见操作技巧
2017/09/01 Javascript
详解vue项目首页加载速度优化
2017/10/18 Javascript
JS扁平化输出数组的2种方法解析
2019/09/17 Javascript
解决removeEventListener 无法清除监听的问题
2020/10/30 Javascript
Python3中使用urllib的方法详解(header,代理,超时,认证,异常处理)
2016/09/21 Python
利用Celery实现Django博客PV统计功能详解
2017/05/08 Python
Python字典,函数,全局变量代码解析
2017/12/18 Python
python的格式化输出(format,%)实例详解
2018/06/01 Python
Windows下将Python文件打包成.EXE可执行文件的方法
2018/08/03 Python
Python3内置模块pprint让打印比print更美观详解
2019/06/02 Python
Python3批量生成带logo的二维码方法
2019/06/24 Python
Tensorflow进行多维矩阵的拆分与拼接实例
2020/02/07 Python
Python Json数据文件操作原理解析
2020/05/09 Python
CSS3实现时间轴效果
2016/07/11 HTML / CSS
用css3写出气球样式的示例代码
2017/09/11 HTML / CSS
九州传奇上机题
2014/07/10 面试题
公司成立感言
2014/01/11 职场文书
先进德育工作者事迹材料
2014/01/24 职场文书
报效祖国演讲稿
2014/09/15 职场文书
教师个人考察材料
2014/12/16 职场文书
幼儿园感谢信
2015/01/21 职场文书
2016年社区“6.26”禁毒日宣传活动总结
2016/04/05 职场文书