Python 多线程共享变量的实现示例


Posted in Python onApril 17, 2020

多线程-共享全局变量

#coding=utf-8
from threading import Thread
import time

g_num = 100

def work1():
 global g_num
 for i in range(3):
  g_num += 1

 print("----in work1, g_num is %d---"%g_num)


def work2():
 global g_num
 print("----in work2, g_num is %d---"%g_num)


print("---线程创建之前g_num is %d---"%g_num)

t1 = Thread(target=work1)
t1.start()

#延时一会,保证t1线程中的事情做完
time.sleep(1)

t2 = Thread(target=work2)
t2.start()

执行如下:

[root@server01 many_task]# python test5.py
---线程创建之前g_num is 100---
----in work1, g_num is 103---
----in work2, g_num is 103---
[root@server01 many_task]#

从上面两个线程执行的结果来看,线程t1将 g_num 加到 103,在线程t2也是打印g_num=103。所以对于两个线程,g_num这个全局变量是共享的。

列表当做实参传递到线程中

#coding=utf-8
from threading import Thread
import time

def work1(nums):
 nums.append(44)
 print("----in work1---",nums)

def work2(nums):
 #延时一会,保证t1线程中的事情做完
 time.sleep(1)
 print("----in work2---",nums)

g_nums = [11,22,33]

t1 = Thread(target=work1, args=(g_nums,))
t1.start()

t2 = Thread(target=work2, args=(g_nums,))
t2.start()

运行如下:

[root@server01 many_task]# python test6.py
('----in work1---', [11, 22, 33, 44])
('----in work2---', [11, 22, 33, 44])

总结:
在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据
缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)

多线程-共享全局变量问题

多线程开发可能遇到的问题

假设两个线程t1和t2都要对全局变量g_num(默认是0)进行加1运算,t1和t2都各对g_num加10次,g_num的最终的结果应该为20。

但是由于是多线程同时操作,有可能出现下面情况:

在g_num=0时,t1取得g_num=0。此时系统把t1调度为”sleeping”状态,把t2转换为”running”状态,t2也获得g_num=0
然后t2对得到的值进行加1并赋给g_num,使得g_num=1
然后系统又把t2调度为”sleeping”,把t1转为”running”。线程t1又把它之前得到的0加1后赋值给g_num。
这样导致虽然t1和t2都对g_num加1,但结果仍然是g_num=1

编写代码测试如下:

[root@server01 many_task]# vim test4.py 

#coding=utf-8
import threading
from time import sleep,ctime

# 初始化g_num
g_num = 0

def add_func1(num):
 global g_num
 for i in range(num):
  g_num += 1
  print("add_func1,第%d次,g_num等于%d" % (i,g_num))
  #sleep(0.5)

def add_func2(num):
 global g_num
 for i in range(num):
  g_num += 1
  print("add_func2,第%d次,g_num等于%d" % (i,g_num))
  #sleep(0.5)

def main():
 # 执行线程
 t1 = threading.Thread(target=add_func1,args=(100,))
 t2 = threading.Thread(target=add_func2,args=(100,))

 t1.start()
 t2.start()

 # 判断当线程存在,则等待1秒
 while len(threading.enumerate()) > 1:
  sleep(1)

 print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)

if __name__ == '__main__':
 main()

执行如下:

add_func2,第96次,g_num等于197
add_func2,第97次,g_num等于198
add_func2,第98次,g_num等于199
add_func2,第99次,g_num等于200
2个线程对同一个全局变量操作之后的最终结果是:200
[root@server01 many_task]#

两个线程虽然执行很快,但是g_num恰好就是100+100=200的结果,是正确的。不过,这个数量少,可能看不出问题来。

测试示例2

[root@server01 many_task]# vim test7.py 

def work1(num):
 global g_num
 for i in range(num):
  g_num += 1
 print("----in work1, g_num is %d---"%g_num)


def work2(num):
 global g_num
 for i in range(num):
  g_num += 1
 print("----in work2, g_num is %d---"%g_num)


print("---线程创建之前g_num is %d---"%g_num)

t1 = threading.Thread(target=work1, args=(10000000,))
t1.start()

t2 = threading.Thread(target=work2, args=(10000000,))
t2.start()

while len(threading.enumerate()) != 1:
 time.sleep(1)

print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)

运行如下:

[root@server01 many_task]# python test7.py
---线程创建之前g_num is 0---
----in work1, g_num is 11977799---
----in work2, g_num is 19108796---
2个线程对同一个全局变量操作之后的最终结果是:19108796
[root@server01 many_task]#

正确的结果应该是:20000000

结论

如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确

到此这篇关于Python 多线程共享变量的实现示例的文章就介绍到这了,更多相关Python 多线程共享变量内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python获取apk文件URL地址实例
Nov 01 Python
Python赋值语句后逗号的作用分析
Jun 08 Python
Python编程中字符串和列表的基本知识讲解
Oct 14 Python
Django实现支付宝付款和微信支付的示例代码
Jul 25 Python
Django 中自定义 Admin 样式与功能的实现方法
Jul 04 Python
Django框架视图介绍与使用详解
Jul 18 Python
在python中实现同行输入/接收多个数据的示例
Jul 20 Python
Django Rest framework频率原理与限制
Jul 26 Python
Python实现使用dir获取类的方法列表
Dec 24 Python
Python 跨.py文件调用自定义函数说明
Jun 01 Python
安装pyecharts1.8.0版本后导入pyecharts模块绘图时报错: “所有图表类型将在 v1.9.0 版本开始强制使用 ChartItem 进行数据项配置 ”的解决方法
Aug 18 Python
pandas数据分组groupby()和统计函数agg()的使用
Mar 04 Python
matplotlib 对坐标的控制,加图例注释的操作
Apr 17 #Python
matplotlib quiver箭图绘制案例
Apr 17 #Python
更新升级python和pip版本后不生效的问题解决
Apr 17 #Python
浅谈python多线程和多线程变量共享问题介绍
Apr 17 #Python
使用Matplotlib绘制不同颜色的带箭头的线实例
Apr 17 #Python
matplotlib 曲线图 和 折线图 plt.plot()实例
Apr 17 #Python
Python实现自动打开电脑应用的示例代码
Apr 17 #Python
You might like
如何用C语言编写PHP扩展的详解
2013/06/13 PHP
php实现获取文件mime类型的方法
2015/02/11 PHP
PHP实现的XML操作类【XML Library】
2016/12/29 PHP
[原创]php正则删除html代码中class样式属性的方法
2017/05/24 PHP
PHP在弹框中获取foreach中遍历的id值并传递给地址栏
2017/06/13 PHP
PHP连接及操作PostgreSQL数据库的方法详解
2019/01/30 PHP
利用PHP如何统计Nginx日志的User Agent数据
2019/03/06 PHP
javascript类继承机制的原理分析
2009/09/12 Javascript
js 刷新页面的代码小结 推荐
2010/04/02 Javascript
教你如何使用firebug调试功能了解javascript闭包和this
2015/03/04 Javascript
javascript跨域方法、原理以及出现问题解决方法(详解)
2015/08/06 Javascript
基于Flowplayer打造一款免费的WEB视频播放器附源码
2015/09/06 Javascript
js移动焦点到最后位置的简单方法
2016/11/25 Javascript
angular2 ng build部署后base文件路径问题详细解答
2017/07/15 Javascript
一文让你彻底搞清楚javascript中的require、import与export
2017/09/24 Javascript
vue-cli下的vuex的简单Demo图解(实现加1减1操作)
2018/02/26 Javascript
Makefile/cmake/node-gyp中区分判断不同平台的方法
2018/12/18 Javascript
JS重学系列之聊聊new操作符
2019/03/04 Javascript
优化Vue项目编译文件大小的方法步骤
2019/05/27 Javascript
Vue发布项目实例讲解
2019/07/17 Javascript
thinkjs微信中控之微信鉴权登陆的实现代码
2019/08/08 Javascript
nodeJs项目在阿里云的简单部署
2020/11/27 NodeJs
利用JavaScript模拟京东按键输入功能
2020/12/01 Javascript
Python 命令行非阻塞输入的小例子
2013/09/27 Python
Python类的动态修改的实例方法
2017/03/24 Python
python模拟事件触发机制详解
2018/01/19 Python
python opencv 读取本地视频文件 修改ffmpeg的方法
2019/01/26 Python
python对验证码降噪的实现示例代码
2019/11/12 Python
html5指南-7.geolocation结合google maps开发一个小的应用
2013/01/07 HTML / CSS
日本土著品牌,综合型购物网站:Cecile
2016/08/23 全球购物
Corelle官方网站:购买康宁餐具
2016/11/02 全球购物
Merrell迈乐澳大利亚网站:购买户外登山鞋
2017/05/28 全球购物
ParcelABC西班牙:包裹运送和快递服务
2019/12/24 全球购物
纪念九一八事变演讲稿1000字
2014/09/14 职场文书
2016年学习贯彻十八届五中全会精神心得体会
2016/01/05 职场文书
MySQL提升大量数据查询效率的优化神器
2022/07/07 MySQL