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 相关文章推荐
pydev使用wxpython找不到路径的解决方法
Feb 10 Python
python实现根据用户输入从电影网站获取影片信息的方法
Apr 07 Python
python使用webdriver爬取微信公众号
Aug 31 Python
使用tensorflow实现线性svm
Sep 07 Python
Django框架模板注入操作示例【变量传递到模板】
Dec 19 Python
django中SMTP发送邮件配置详解
Jul 19 Python
python抓取多种类型的页面方法实例
Nov 20 Python
python序列化与数据持久化实例详解
Dec 20 Python
Python 实现日志同时输出到屏幕和文件
Feb 19 Python
使用 django orm 写 exists 条件过滤实例
May 20 Python
基于K.image_data_format() == 'channels_first' 的理解
Jun 29 Python
10个python爬虫入门基础代码实例 + 1个简单的python爬虫完整实例
Dec 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
Yii中CArrayDataProvider和CActiveDataProvider区别实例分析
2016/03/02 PHP
JQuery 无废话系列教程(一) jquery入门 [推荐]
2009/06/23 Javascript
c#和Javascript操作同一json对象的实现代码
2012/01/17 Javascript
javascript删除option选项的多种方法总结
2013/11/22 Javascript
深入剖析JavaScript中的枚举功能
2014/03/06 Javascript
js拼接html注意问题示例探讨
2014/07/14 Javascript
一个JavaScript用逗号分割字符串实例
2014/09/22 Javascript
Bootstrap每天必学之导航条
2015/11/27 Javascript
jQuery操作动态生成的内容的方法
2016/05/28 Javascript
浅谈JavaScript前端开发的MVC结构与MVVM结构
2016/06/03 Javascript
JS限制条件补全问题实例分析
2016/12/16 Javascript
原生js实现商品放大镜效果
2017/01/12 Javascript
js学习总结_轮播图之渐隐渐现版(实例讲解)
2017/07/17 Javascript
AngularJS service之select下拉菜单效果
2017/07/28 Javascript
webpack开发跨域问题解决办法
2017/08/03 Javascript
React-Native中禁用Navigator手势返回的示例代码
2017/09/09 Javascript
Vue用v-for给循环标签自身属性添加属性值的方法
2018/10/18 Javascript
详解key在Vue列表渲染时究竟起到了什么作用
2019/04/20 Javascript
微信小程序错误this.setData报错及解决过程
2019/09/18 Javascript
Jquery Fade用法详解
2020/11/06 jQuery
javascript实现倒计时提示框
2021/03/02 Javascript
Python matplotlib 画图窗口显示到gui或者控制台的实例
2018/05/24 Python
使用python爬取抖音视频列表信息
2019/07/15 Python
Python使用monkey.patch_all()解决协程阻塞问题
2020/04/15 Python
澳大利亚鞋仓库:Shoe Warehouse
2019/07/25 全球购物
Flesh Beauty官网:露华浓集团旗下彩妆品牌
2021/02/15 全球购物
学前教育求职自荐信范文
2013/12/25 职场文书
蛋糕店创业计划书
2014/05/06 职场文书
承诺书格式
2014/06/03 职场文书
2014年统计工作总结
2014/11/21 职场文书
2014年合同管理工作总结
2014/12/02 职场文书
会计入职心得体会
2016/01/22 职场文书
未来,这5大方向都很适合创业
2019/07/22 职场文书
导游词之泰山玉皇顶
2019/12/23 职场文书
原生JS封装vue Tab切换效果
2021/04/28 Vue.js
vue生命周期钩子函数以及触发时机
2022/04/26 Vue.js