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 相关文章推荐
python3使用tkinter实现ui界面简单实例
Jan 10 Python
用pywin32实现windows模拟鼠标及键盘动作
Apr 22 Python
Python3读取zip文件信息的方法
May 22 Python
基于python的Tkinter实现一个简易计算器
Dec 31 Python
Python打包可执行文件的方法详解
Sep 19 Python
利用python编写一个图片主色转换的脚本
Dec 07 Python
详解Python判定IP地址合法性的三种方法
Mar 06 Python
Django Form 实时从数据库中获取数据的操作方法
Jul 25 Python
Python随机函数库random的使用方法详解
Aug 21 Python
Python 实现Numpy中找出array中最大值所对应的行和列
Nov 26 Python
numpy.linalg.eig() 计算矩阵特征向量方式
Nov 29 Python
python3.6中anaconda安装sklearn踩坑实录
Jul 28 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编程效率 引入缓存机制提升性能
2010/02/15 PHP
基于PHP实现等比压缩图片大小
2016/03/04 PHP
PHPMailer发送邮件
2016/12/28 PHP
PHP+原生态ajax实现的省市联动功能详解
2017/08/15 PHP
Laravel+Intervention实现上传图片功能示例
2019/07/09 PHP
深入解析PHP底层机制及相关原理
2020/12/11 PHP
用js实现下载远程文件并保存在本地的脚本
2008/05/06 Javascript
把input初始值不写value的具体实现方法
2013/07/04 Javascript
jquery 根据name名获取元素的value值
2015/02/27 Javascript
超漂亮的jQuery图片轮播特效
2015/11/24 Javascript
canvas快速绘制圆形、三角形、矩形、多边形方法介绍
2016/12/29 Javascript
jQuery实现点击下拉框中的值累加到文本框中的方法示例
2017/10/28 jQuery
Node.js学习教程之HTTP/2服务器推送【译】
2017/10/31 Javascript
JS在if中的强制类型转换方式
2018/07/15 Javascript
微信小程序版本自动更新的方法
2019/06/14 Javascript
javascript面向对象三大特征之多态实例详解
2019/07/24 Javascript
实例分析JS中的相等性判断===、 ==和Object.is()
2019/11/17 Javascript
Vue实现计算器计算效果
2020/08/17 Javascript
vue中如何添加百度统计代码
2020/12/19 Vue.js
python中from module import * 的一个坑
2014/07/20 Python
python @property的用法及含义全面解析
2018/02/01 Python
Python3.6.x中内置函数总结及讲解
2019/02/22 Python
一款利用html5和css3动画排列人物头像的实例演示
2014/12/05 HTML / CSS
英国最大的奢侈品零售网络商城:Flannels
2016/09/16 全球购物
Feelunique德国官方网站:欧洲最大的在线美容零售商
2019/07/20 全球购物
戴尔英国翻新电脑和电子产品:Dell UK Refurbished Computers
2019/07/30 全球购物
adidas泰国官网:adidas TH
2020/07/11 全球购物
中药学专业求职信
2014/05/31 职场文书
医生爱岗敬业演讲稿
2014/08/26 职场文书
喝酒驾驶检讨书
2014/10/01 职场文书
公司门卫岗位职责
2015/04/13 职场文书
信仰纪录片观后感
2015/06/08 职场文书
SQLServer2019 数据库环境搭建与使用的实现
2021/04/08 SQL Server
golang slice元素去重操作
2021/04/30 Golang
react antd实现动态增减表单
2021/06/03 Javascript
详解Python flask的前后端交互
2022/03/31 Python