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和php通信乱码问题解决方法
Apr 15 Python
Python脚本简单实现打开默认浏览器登录人人和打开QQ的方法
Apr 12 Python
浅谈python中列表、字符串、字典的常用操作
Sep 19 Python
Python使用django框架实现多人在线匿名聊天的小程序
Nov 29 Python
Flask和Django框架中自定义模型类的表名、父类相关问题分析
Jul 19 Python
Django代码性能优化与Pycharm Profile使用详解
Aug 26 Python
Python的argparse库使用详解
Oct 09 Python
浅谈python的输入输出,注释,基本数据类型
Apr 02 Python
Python列表解析操作实例总结
Feb 26 Python
python同时遍历两个list用法说明
May 02 Python
python安装sklearn模块的方法详解
Nov 28 Python
实操Python爬取觅知网素材图片示例
Nov 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双引号中访问数组元素报错的解决方法
2018/02/01 PHP
asp.net和php的区别点总结
2019/10/10 PHP
jQuery下的几个你可能没用过的功能
2010/08/29 Javascript
javascript字符串替换及字符串分割示例代码
2013/12/12 Javascript
jquery模拟LCD 时钟的html文件源代码
2014/06/16 Javascript
JQuery.Ajax()的data参数类型实例详解
2015/11/20 Javascript
修改jquery中dialog的title属性方法(推荐)
2016/08/26 Javascript
Angular的事件和表单详解
2016/12/26 Javascript
js模态对话框使用方法详解
2017/02/16 Javascript
vuejs父子组件之间数据交互详解
2017/08/09 Javascript
vue中的计算属性的使用和vue实例的方法示例
2017/12/04 Javascript
Vue2.5学习笔记之如何在项目中使用和配置Vue
2018/09/26 Javascript
JS实现的tab切换并显示相应内容模块功能示例
2019/08/03 Javascript
python3实现TCP协议的简单服务器和客户端案例(分享)
2017/06/14 Python
Python单体模式的几种常见实现方法详解
2017/07/28 Python
利用python将pdf输出为txt的实例讲解
2018/04/23 Python
selenium+python自动化测试之使用webdriver操作浏览器的方法
2019/01/23 Python
代码详解django中数据库设置
2019/01/28 Python
Python绘制堆叠柱状图的实例
2019/07/09 Python
Django CBV与FBV原理及实例详解
2019/08/12 Python
python 字典的打印实现
2019/09/26 Python
python使用pygame实现笑脸乒乓球弹珠球游戏
2019/11/25 Python
通过 Python 和 OpenCV 实现目标数量监控
2020/01/05 Python
Windows系统下pycharm中的pip换源
2020/02/23 Python
PyCharm中如何直接使用Anaconda已安装的库
2020/05/28 Python
Python调用OpenCV实现图像平滑代码实例
2020/06/19 Python
python从Oracle读取数据生成图表
2020/10/14 Python
使用HTML5做个画图板的方法介绍
2013/05/03 HTML / CSS
amazeui页面分析之登录页面的示例代码
2020/08/25 HTML / CSS
美国汽配连锁巨头Pep Boys官网:轮胎更换、汽车维修服务和汽车零部件
2017/01/14 全球购物
介绍一下javax.servlet.Servlet接口及其主要方法
2015/11/30 面试题
关于幼儿的自我评价
2013/12/18 职场文书
《那片绿绿的爬山虎》教学反思
2014/02/27 职场文书
业务内勤岗位职责
2014/04/30 职场文书
营销总经理岗位职责范本
2014/09/02 职场文书
使用redis实现延迟通知功能(Redis过期键通知)
2021/09/04 Redis