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 相关文章推荐
Python2.5/2.6实用教程 入门基础篇
Nov 29 Python
Pycharm 操作Django Model的简单运用方法
May 23 Python
django1.11.1 models 数据库同步方法
May 30 Python
使用Python的toolz库开始函数式编程的方法
Nov 15 Python
Python中GeoJson和bokeh-1的使用讲解
Jan 03 Python
python 实现视频 图像帧提取
Dec 10 Python
python 画条形图(柱状图)实例
Apr 24 Python
python能开发游戏吗
Jun 11 Python
Python计算矩阵的和积的实例详解
Sep 10 Python
如何基于python实现年会抽奖工具
Oct 20 Python
python+opencv实现车道线检测
Feb 19 Python
python numpy中setdiff1d的用法说明
Apr 22 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
php下将图片以二进制存入mysql数据库中并显示的实现代码
2010/05/27 PHP
PHP自定义大小验证码的方法详解
2013/06/07 PHP
php实现图片添加水印功能
2014/02/13 PHP
CentOS 7.2 下编译安装PHP7.0.10+MySQL5.7.14+Nginx1.10.1的方法详解(mini版本)
2016/09/01 PHP
php判断是否连接上网络的方法实例详解
2016/12/14 PHP
PHP中的empty、isset、isnull的区别与使用实例
2019/03/22 PHP
获取div编辑框,textarea,input text的光标位置 兼容IE,FF和Chrome的方法介绍
2012/11/08 Javascript
uploadify在Firefox下丢失session问题的解决方法
2013/08/07 Javascript
js AppendChild与insertBefore用法详细对比
2013/12/16 Javascript
jQuery文件上传插件Uploadify使用指南
2014/06/05 Javascript
js获取元素相对窗口位置的实现代码
2014/09/28 Javascript
返回顶部按钮响应滚动且动态显示与隐藏
2014/10/14 Javascript
AngularJS基础知识笔记之表格
2015/05/10 Javascript
JavaScript ES6的新特性使用新方法定义Class
2016/06/28 Javascript
jQuery事件_动力节点Java学院整理
2017/07/05 jQuery
Angular实现类似博客评论的递归显示及获取回复评论的数据
2017/11/06 Javascript
详解基于Vue cli生成的Vue项目的webpack4升级
2018/06/19 Javascript
使用layer弹窗提交表单时判断表单是否输入为空的例子
2019/09/26 Javascript
js实现点击生成随机div
2020/01/16 Javascript
[44:43]完美世界DOTA2联赛决赛日 FTD vs GXR 第一场 11.08
2020/11/11 DOTA
[51:39]DOTA2-DPC中国联赛 正赛 Magma vs LBZS BO3 第二场 2月7日
2021/03/11 DOTA
pyside写ui界面入门示例
2014/01/22 Python
Python运算符重载详解及实例代码
2017/03/07 Python
手动安装python3.6的操作过程详解
2020/01/13 Python
Python可变对象与不可变对象原理解析
2020/02/25 Python
5行Python代码实现图像分割的步骤详解
2020/05/25 Python
python实现单机五子棋
2020/08/28 Python
HMV日本官网:全球知名的音乐、DVD和电脑游戏零售巨头
2016/08/13 全球购物
迷你唐卡软皮鞋:Minnetonka Moccasin
2018/05/01 全球购物
迷你分体式空调:SoGoodToBuy
2018/08/07 全球购物
自动化专业毕业生求职信
2014/06/18 职场文书
2015年共青团工作总结
2015/05/15 职场文书
运动会广播稿300字
2015/08/19 职场文书
员工安全责任协议书
2016/03/22 职场文书
创业计划书之网络外卖
2019/10/31 职场文书
CSS文本阴影 text-shadow 悬停效果详解
2022/05/25 HTML / CSS