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采用Django制作简易的知乎日报API
Aug 03 Python
使用pyecharts在jupyter notebook上绘图
Apr 23 Python
Python用 KNN 进行验证码识别的实现方法
Feb 06 Python
python实现一组典型数据格式转换
Dec 15 Python
python使用wxpy轻松实现微信防撤回的方法
Feb 21 Python
利用python将图片版PDF转文字版PDF
May 03 Python
Python实现字符型图片验证码识别完整过程详解
May 10 Python
Windows下PyCharm2018.3.2 安装教程(图文详解)
Oct 24 Python
matplotlib.pyplot画图并导出保存的实例
Dec 07 Python
pygame实现飞机大战
Mar 11 Python
使用Python封装excel操作指南
Jan 29 Python
如何在Python中妥善使用进度条详解
Apr 05 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删除文本文件中重复行的方法
2015/04/28 PHP
实例简介PHP的一些高级面向对象编程的特性
2015/11/27 PHP
学习php设计模式 php实现装饰器模式(decorator)
2015/12/07 PHP
变量在 PHP7 内部的实现(二)
2015/12/21 PHP
Code: write(s,d) 输出连续字符串
2007/08/19 Javascript
Extjs TimeField 显示正常时间格式的代码
2011/06/28 Javascript
js调用打印机打印网页字体总是缩小一号的解决方法
2014/01/24 Javascript
DIV始终居中的js代码
2014/02/17 Javascript
js实现同一页面可多次调用的图片幻灯切换效果
2015/02/28 Javascript
js实现仿阿里巴巴城市选择框效果实例
2015/06/24 Javascript
JS+CSS实现简易实用的滑动门菜单效果
2015/09/18 Javascript
使用JQuery实现Ctrl+Enter提交表单的方法
2015/10/22 Javascript
Jquery元素追加和删除的实现方法
2016/05/24 Javascript
JavaScript实现垂直向上无缝滚动特效代码
2016/11/23 Javascript
jQuery实现判断控件是否显示的方法
2017/01/11 Javascript
微信小程序之左右布局的实现代码
2019/12/13 Javascript
Vue实现星级评价效果实例详解
2019/12/30 Javascript
使用vue cli4.x搭建vue项目的过程详解
2020/05/08 Javascript
jQuery加PHP实现图片上传并提交的示例代码
2020/07/16 jQuery
Python基于辗转相除法求解最大公约数的方法示例
2018/04/04 Python
python 构造三维全零数组的方法
2018/11/12 Python
对python读取zip压缩文件里面的csv数据实例详解
2019/02/08 Python
python 杀死自身进程的实现方法
2019/07/01 Python
远程部署工具Fabric详解(支持Python3)
2019/07/04 Python
django中使用Celery 布式任务队列过程详解
2019/07/29 Python
django重新生成数据库中的某张表方法
2019/08/28 Python
Django中的模型类设计及展示示例详解
2020/05/29 Python
Python+PyQt5+MySQL实现天气管理系统
2020/06/16 Python
Python paramiko使用方法代码汇总
2020/11/20 Python
华润集团网上药店:健一网
2016/09/19 全球购物
大学生学习党课思想汇报
2014/01/03 职场文书
怎样写好自我评价呢?
2014/02/16 职场文书
相亲大会策划方案
2014/06/05 职场文书
2015年留守儿童工作总结
2015/05/22 职场文书
傲慢与偏见电影观后感
2015/06/10 职场文书
Python合并多张图片成PDF
2021/06/09 Python