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 相关文章推荐
使用pdb模块调试Python程序实例
Jun 02 Python
Python3实战之爬虫抓取网易云音乐的热门评论
Oct 09 Python
Python基于辗转相除法求解最大公约数的方法示例
Apr 04 Python
python使用turtle库与random库绘制雪花
Jun 22 Python
django利用request id便于定位及给日志加上request_id
Aug 26 Python
python实现代码统计程序
Sep 19 Python
python3实现elasticsearch批量更新数据
Dec 03 Python
python随机模块random使用方法详解
Feb 14 Python
30行Python代码实现高分辨率图像导航的方法
May 22 Python
python 图像判断,清晰度(明暗),彩色与黑白实例
Jun 04 Python
Python实现网络聊天室的示例代码(支持多人聊天与私聊)
Jan 27 Python
http通过StreamingHttpResponse完成连续的数据传输长链接方式
Feb 12 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制作简单的内容采集器的代码
2007/11/28 PHP
修改php.ini不生效问题解决方法(上传大于8M的文件)
2013/06/14 PHP
php中stream(流)的用法
2014/03/25 PHP
phpMyAdmin自动登录和取消自动登录的配置方法
2014/05/12 PHP
php 批量查询搜狗sogou代码分享
2015/05/17 PHP
php制作的简单验证码识别代码
2016/01/26 PHP
php7下的filesize函数
2019/09/30 PHP
Prototype的Class.create函数解析
2011/09/22 Javascript
扩展Jquery插件处理mouseover时内部有子元素时发生样式闪烁
2011/12/08 Javascript
js实现jquery的offset()方法实例
2015/01/10 Javascript
MvcPager分页控件 适用于Bootstrap
2017/06/03 Javascript
vue不通过路由直接获取url中参数的方法示例
2017/08/24 Javascript
Vue 中的compile操作方法
2018/02/26 Javascript
nuxt框架中路由鉴权之Koa和Session的用法
2018/05/09 Javascript
Vue插槽原理与用法详解
2019/03/05 Javascript
详解小程序退出页面时清除定时器
2019/04/28 Javascript
mpvue实现左侧导航与右侧内容的联动
2019/10/21 Javascript
vue双向绑定数据限制长度的方法
2019/11/04 Javascript
Nodejs使用archiver-zip-encrypted库加密压缩文件时报错(解决方案)
2019/11/18 NodeJs
在实例中重学JavaScript事件循环
2020/12/03 Javascript
Python中如何使用if语句处理列表实例代码
2019/02/24 Python
利用Tensorflow的队列多线程读取数据方式
2020/02/05 Python
Python图像处理库PIL的ImageDraw模块介绍详解
2020/02/26 Python
Python动态导入模块:__import__、importlib、动态导入的使用场景实例分析
2020/03/30 Python
python selenium 获取接口数据的实现
2020/12/07 Python
python实现发送QQ邮件(可加附件)
2020/12/23 Python
CSS3 真的会替代 SCSS 吗
2021/03/09 HTML / CSS
Html5原生拖拽相关事件简介以及基础实现
2020/11/19 HTML / CSS
C#里面可以避免一个类被其他类继承么?如何?
2013/09/26 面试题
do you have any Best Practice for testing
2016/06/04 面试题
企业与个人合作经营协议书
2014/11/01 职场文书
小学音乐教师个人工作总结
2015/02/05 职场文书
社会实践活动总结
2015/02/05 职场文书
学习型家庭事迹材料(2016精选版)
2016/02/29 职场文书
2019年二手房买卖合同范本
2019/10/14 职场文书
Redis持久化与主从复制的实践
2021/04/27 Redis