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 相关文章推荐
Django 前后台的数据传递的方法
Aug 08 Python
PHP实现发送和接收JSON请求
Jun 07 Python
python numpy和list查询其中某个数的个数及定位方法
Jun 27 Python
python3.x 将byte转成字符串的方法
Jul 17 Python
Python多进程与服务器并发原理及用法实例分析
Aug 21 Python
Python爬取视频(其实是一篇福利)过程解析
Aug 01 Python
django-filter和普通查询的例子
Aug 12 Python
Django实现文件上传和下载功能
Oct 06 Python
python pygame实现挡板弹球游戏
Nov 25 Python
使用Tensorboard工具查看Loss损失率
Feb 15 Python
python 实现数据库中数据添加、查询与更新的示例代码
Dec 07 Python
详解Python 中的 defaultdict 数据类型
Feb 22 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加密解密的代码
2007/07/16 PHP
IIS php环境配置PHP5 MySQL5 ZendOptimizer phpmyadmin安装与配置
2008/11/18 PHP
PHP安全配置详细说明
2011/09/26 PHP
PHP实现简单汉字验证码
2015/07/28 PHP
Laravel与CI框架中截取字符串函数
2016/05/08 PHP
php中各种定义变量的方法小结
2017/10/18 PHP
Javascript解决常见浏览器兼容问题的12种方法
2010/01/04 Javascript
js定义对象或数组直接量时各浏览器对多余逗号的处理(json)
2011/03/05 Javascript
jquery实现文本框数量加减功能的例子分享
2014/05/10 Javascript
js处理表格对table进行修饰
2014/05/26 Javascript
JS实现窗口加载时模拟鼠标移动的方法
2015/06/03 Javascript
同步文本框内容JS代码实现
2016/08/04 Javascript
JavaScript实现事件的中断传播和行为阻止方法示例
2017/01/20 Javascript
axios学习教程全攻略
2017/03/26 Javascript
微信小程序基于slider组件动态修改标签透明度的方法示例
2017/12/04 Javascript
nodejs 最新版安装npm 的使用详解
2018/01/18 NodeJs
JavaScript设计模式之代理模式实例分析
2019/01/16 Javascript
Node.js实现一个HTTP服务器的方法示例
2019/05/13 Javascript
Vue+elementui 实现复杂表头和动态增加列的二维表格功能
2019/09/23 Javascript
javascript实现鼠标点击生成文字特效
2019/12/24 Javascript
多版本Python共存的配置方法
2017/05/22 Python
Python使用matplotlib绘制余弦的散点图示例
2018/03/14 Python
Python中循环引用(import)失败的解决方法
2018/04/22 Python
浅谈pytorch grad_fn以及权重梯度不更新的问题
2019/08/20 Python
flask项目集成swagger的方法
2020/12/09 Python
前后端结合实现amazeUI分页效果
2020/08/21 HTML / CSS
澳大利亚最超值的自行车之家:Reid Cycles
2019/03/24 全球购物
美国优质马术服装购买网站:Breeches.com
2019/12/16 全球购物
如何写求职信
2014/05/24 职场文书
岗位职责说明书模板
2014/07/30 职场文书
经贸日语专业自荐信
2014/09/02 职场文书
领导干部四风问题自我剖析材料
2014/09/25 职场文书
给老婆的保证书
2015/01/16 职场文书
2015年部门工作总结范文
2015/03/31 职场文书
导游词之茶卡盐湖
2019/11/26 职场文书
golang在GRPC中设置client的超时时间
2021/04/27 Golang