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多线程http下载实现示例
Dec 30 Python
python实现多线程抓取知乎用户
Dec 12 Python
numpy中实现二维数组按照某列、某行排序的方法
Apr 04 Python
python验证码识别教程之滑动验证码
Jun 04 Python
Flask框架单例模式实现方法详解
Jul 31 Python
pycharm配置git(图文教程)
Aug 16 Python
python滑块验证码的破解实现
Nov 10 Python
python 实现批量替换文本中的某部分内容
Dec 13 Python
Python实现搜索算法的实例代码
Jan 02 Python
Django实现celery定时任务过程解析
Apr 21 Python
浅析关于Keras的安装(pycharm)和初步理解
Oct 23 Python
pytest配置文件pytest.ini的详细使用
Apr 17 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安全开发库中文详细介绍
2015/03/22 PHP
javascript mouseover、mouseout停止事件冒泡的解决方案
2009/04/07 Javascript
JS判断是否为数字,是否为整数,是否为浮点数的代码
2010/04/24 Javascript
面向对象Javascript核心支持代码分享
2012/05/23 Javascript
js DOM 元素ID就是全局变量
2012/09/20 Javascript
jquery 缓存问题的几个解决方法
2013/11/11 Javascript
jQuery解析XML文件同时动态增加js文件的方法
2015/06/01 Javascript
JavaScript动态创建div等元素实例讲解
2016/01/06 Javascript
Node.js实用代码段之获取Buffer对象字节长度
2016/03/17 Javascript
jQuery滚动监听实现商城楼梯式导航效果
2017/03/06 Javascript
详解vue中localStorage的使用方法
2018/11/22 Javascript
使用koa2创建web项目的方法步骤
2019/03/12 Javascript
通过JS深度判断两个对象字段相同
2019/06/14 Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
2020/02/10 Javascript
基于JS实现操作成功之后自动跳转页面
2020/09/25 Javascript
python实现简单温度转换的方法
2015/03/13 Python
python实现员工管理系统
2018/01/11 Python
Django自定义用户认证示例详解
2018/03/14 Python
JSON文件及Python对JSON文件的读写操作
2018/10/07 Python
Python实现查找二叉搜索树第k大的节点功能示例
2019/01/24 Python
如何通过python画loss曲线的方法
2019/06/26 Python
Python3从零开始搭建一个语音对话机器人的实现
2019/08/23 Python
Python序列化pickle模块使用详解
2020/03/05 Python
python将logging模块封装成单独模块并实现动态切换Level方式
2020/05/12 Python
Python加速程序运行的方法
2020/07/29 Python
Python中的特殊方法以及应用详解
2020/09/20 Python
html5 viewport使用方法示例详解
2013/12/02 HTML / CSS
美国非常受欢迎的Spa品牌:Bliss必列斯
2018/04/10 全球购物
机电一体化自荐信
2013/12/10 职场文书
护士个人自我鉴定
2014/03/24 职场文书
物流专业专科生职业生涯规划书
2014/09/14 职场文书
2014年话务员工作总结
2014/11/19 职场文书
2014年英语教学工作总结
2014/12/17 职场文书
爱的教育观后感
2015/06/17 职场文书
nginx共享内存的机制详解
2022/03/21 Servers
vue代码分块和懒加载非必要资源文件
2022/04/11 Vue.js