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对两个有序列表进行合并和排序的例子
Jun 13 Python
Python中encode()方法的使用简介
May 18 Python
Python类属性的延迟计算
Oct 22 Python
Python中表达式x += y和x = x+y 的区别详解
Jun 20 Python
Python中序列的修改、散列与切片详解
Aug 27 Python
异步任务队列Celery在Django中的使用方法
Jun 07 Python
PyQt4实时显示文本内容GUI的示例
Jun 14 Python
解决pycharm 工具栏Tool中找不到Run manager.py Task的问题
Jul 01 Python
python 求某条线上特定x值或y值的点坐标方法
Jul 09 Python
Python占用的内存优化教程
Jul 28 Python
python基础 range的用法解析
Aug 23 Python
详解Python类和对象内容
Jun 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编程最快明白》第四讲:日期、表单接收、session、cookie
2010/11/01 PHP
php+ajax 实现输入读取数据库显示匹配信息
2015/10/08 PHP
PHP中Static(静态)关键字功能与用法实例分析
2019/04/05 PHP
laravel中Redis队列监听中断的分析
2020/09/14 PHP
JavaScript 打地鼠游戏代码说明
2010/10/12 Javascript
JavaScript学习笔记之获取当前目录的实现代码
2010/12/14 Javascript
js修改原型的属性使用介绍
2014/01/26 Javascript
详解Jquery Easyui的验证扩展
2017/01/09 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
10分钟上手vue-cli 3.0 入门介绍
2018/04/04 Javascript
一个Vue视频媒体多段裁剪组件的实现示例
2018/08/09 Javascript
微信小程序数据分析之自定义分析的实现
2018/08/17 Javascript
js验证身份证号码记录的方法
2019/04/26 Javascript
微信小程序云开发之数据库操作
2019/05/18 Javascript
JS前端广告拦截实现原理解析
2020/02/17 Javascript
jQuery实现图片切换效果
2020/10/19 jQuery
element中Steps步骤条和Tabs标签页关联的解决
2020/12/08 Javascript
Python开发编码规范
2006/09/08 Python
Eclipse + Python 的安装与配置流程
2013/03/05 Python
python基础教程之常用运算符
2014/08/29 Python
python调用百度语音REST API
2018/08/30 Python
利用Pandas和Numpy按时间戳将数据以Groupby方式分组
2019/07/22 Python
Python matplotlib生成图片背景透明的示例代码
2019/08/30 Python
如何在scrapy中捕获并处理各种异常
2020/09/28 Python
关于Python不换行输出和不换行输出end=““不显示的问题(亲测已解决)
2020/10/27 Python
乐高西班牙官方商店:LEGO Shop ES
2019/12/01 全球购物
Puccini乌克兰:购买行李箱、女士手袋网上商店
2020/08/06 全球购物
如何唤起类中的一个方法
2013/11/29 面试题
广告学专业毕业生自荐信
2013/09/24 职场文书
实验教师岗位职责
2014/02/13 职场文书
班主任经验交流会主持词
2014/04/01 职场文书
三分钟英语演讲稿
2014/04/24 职场文书
面试自我介绍演讲稿
2014/04/29 职场文书
安全生产目标管理责任书
2014/07/25 职场文书
一般党员对照检查材料
2014/09/24 职场文书
公务员考察材料
2014/12/23 职场文书