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参数和作用域的使用
Nov 01 Python
python计算书页码的统计数字问题实例
Sep 26 Python
Python 中urls.py:URL dispatcher(路由配置文件)详解
Mar 24 Python
Python优先队列实现方法示例
Sep 21 Python
Python爬虫实例_城市公交网络站点数据的爬取方法
Jan 10 Python
TensorFlow实现创建分类器
Feb 06 Python
Pandas读取并修改excel的示例代码
Feb 17 Python
Python面向对象程序设计之私有属性及私有方法示例
Apr 08 Python
Python中面向对象你应该知道的一下知识
Jul 10 Python
python内存管理机制原理详解
Aug 12 Python
Pycharm 使用 Pipenv 新建的虚拟环境(图文详解)
Apr 16 Python
Pytorch 使用CNN图像分类的实现
Jun 16 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和JAVA中的重载(overload)和覆盖(override) 介绍
2012/03/01 PHP
php调用mysql存储过程实例分析
2014/12/29 PHP
php采集神器cURL使用方法详解
2016/02/19 PHP
简单的pgsql pdo php操作类实现代码
2016/08/25 PHP
php微信公众号开发(4)php实现自定义关键字回复
2016/12/15 PHP
使用Javascript接收get传递的值的代码
2011/11/30 Javascript
下载文件个别浏览器文件名乱码解决办法
2013/03/19 Javascript
动态加载JS文件的三种方法
2013/11/08 Javascript
写JQuery插件的基本知识
2013/11/25 Javascript
jQuery Ajax 异步加载显示等待效果代码分享
2016/08/01 Javascript
AngularJS在IE下取数据总是缓存问题的解决方法
2016/08/05 Javascript
JS实现的RGB网页颜色在线取色器完整实例
2016/12/21 Javascript
Node.js中多进程模块Cluster的介绍与使用
2017/05/27 Javascript
node中Express 动态设置端口的方法
2017/08/04 Javascript
详解js类型判断
2018/05/22 Javascript
JS实现获取进今年第几天是周几的方法分析
2018/06/27 Javascript
p5.js绘制旋转的正方形
2019/10/23 Javascript
js中位数不足自动补位扩展padLeft、padRight实现代码
2020/04/06 Javascript
基于aotu.js实现微信自动添加通讯录中的联系人功能
2020/05/28 Javascript
[02:16]卖萌的僵尸 DOTA2神话信使飞僵小宝来袭
2014/03/24 DOTA
[02:11]2016国际邀请赛中国区预选赛最美TA采访现场玩家
2016/06/28 DOTA
Python3.x对JSON的一些操作示例
2017/09/01 Python
Python进阶之尾递归的用法实例
2018/01/31 Python
对python xlrd读取datetime类型数据的方法详解
2018/12/26 Python
Python如何调用JS文件中的函数
2019/08/16 Python
Python综合应用名片管理系统案例详解
2020/01/03 Python
使用遗传算法求二元函数的最小值
2020/02/11 Python
python发qq消息轰炸虐狗好友思路详解(完整代码)
2020/02/15 Python
在IE6系列等老式浏览器中使用HTML5的新标签实现方案
2012/12/25 HTML / CSS
html5 音乐播放器 audio 标签使用概述
2013/07/15 HTML / CSS
IWOOT美国:新奇的小玩意
2018/04/27 全球购物
内容编辑个人求职信
2013/12/10 职场文书
三月学雷锋月活动总结
2014/04/28 职场文书
2015教师个人年度工作总结
2015/10/23 职场文书
PL350与SW11的比较
2021/04/22 无线电
使用canvas对video视频某一刻截图功能
2021/09/25 HTML / CSS