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 相关文章推荐
django接入新浪微博OAuth的方法
Jun 29 Python
python2.7读取文件夹下所有文件名称及内容的方法
Feb 24 Python
python selenium 获取标签的属性值、内容、状态方法
Jun 22 Python
python的scikit-learn将特征转成one-hot特征的方法
Jul 10 Python
Python操作qml对象过程详解
Sep 26 Python
Django中自定义查询对象的具体使用
Oct 13 Python
python3下pygame如何实现显示中文
Jan 11 Python
Python批量安装卸载1000个apk的方法
Apr 10 Python
Python3之乱码\xe6\x97\xa0\xe6\xb3\x95处理方式
May 11 Python
Python 分布式缓存之Reids数据类型操作详解
Jun 24 Python
python基于opencv实现人脸识别
Jan 04 Python
Python创建自己的加密货币的示例
Mar 01 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 INI配置文件的解析实现分析
2011/01/04 PHP
php中将数组转成字符串并保存到数据库中的函数代码
2013/09/29 PHP
php配置php-fpm启动参数及配置详解
2013/11/04 PHP
php读取3389的脚本
2014/05/06 PHP
php中fgetcsv()函数用法实例
2014/11/28 PHP
php实现屏蔽掉黑帽SEO的搜索关键字
2015/04/15 PHP
TNC vs IO BO3 第一场2.13
2021/03/10 DOTA
为Yahoo! UI Extensions Grid增加内置的可编辑器
2007/03/10 Javascript
jQuery EasyUI API 中文文档 - Form表单
2011/10/06 Javascript
js显示时间 js显示最后修改时间
2013/01/02 Javascript
JavaScript实现网页上的浮动广告的简单方法
2013/06/14 Javascript
js hover 定时器(实例代码)
2013/11/12 Javascript
基于JQuery实现滚动到页面底端时自动加载更多信息
2014/01/31 Javascript
jQuery实现点击图片翻页展示效果的方法
2015/02/16 Javascript
Bootstrap Table表格一直加载(load)不了数据的快速解决方法
2016/09/17 Javascript
原生js实现无限循环轮播图效果
2017/01/20 Javascript
Angular搜索场景中使用rxjs的操作符处理思路
2018/05/30 Javascript
vue引入axios同源跨域问题
2018/09/27 Javascript
详解IOS微信上Vue单页面应用JSSDK签名失败解决方案
2018/11/14 Javascript
微信小程序点击顶部导航栏切换样式代码实例
2019/11/12 Javascript
最全vue的vue-amap使用高德地图插件画多边形范围的示例代码
2020/07/17 Javascript
编写v-for循环的技巧汇总
2020/12/01 Javascript
python中mechanize库的简单使用示例
2014/01/10 Python
python使用三角迭代计算圆周率PI的方法
2015/03/20 Python
详解Python中 sys.argv[]的用法简明解释
2017/12/20 Python
Python3.5基础之函数的定义与使用实例详解【参数、作用域、递归、重载等】
2019/04/26 Python
Python使用贪婪算法解决问题
2019/10/22 Python
浅谈pytorch、cuda、python的版本对齐问题
2020/01/15 Python
CSS3实现多背景模拟动态边框的效果
2016/11/08 HTML / CSS
实例教程 利用html5和css3打造一款创意404页面
2014/10/20 HTML / CSS
德国综合购物网站:OTTO
2018/11/13 全球购物
端口镜像是怎么实现的
2014/03/25 面试题
会计核算科岗位职责
2014/03/19 职场文书
文明礼仪伴我行演讲稿
2014/05/12 职场文书
2015年幼儿教师个人工作总结
2015/05/20 职场文书
八年级作文之我的母亲
2019/12/10 职场文书