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中将阿拉伯数字转换成中文的实现代码
May 19 Python
python基础入门学习笔记(Python环境搭建)
Jan 13 Python
获取Django项目的全部url方法详解
Oct 26 Python
python3大文件解压和基本操作
Dec 15 Python
python opencv之SIFT算法示例
Feb 24 Python
python多进程使用及线程池的使用方法代码详解
Oct 24 Python
Python docx库用法示例分析
Feb 16 Python
numpy数组广播的机制
Jul 12 Python
使用TensorFlow直接获取处理MNIST数据方式
Feb 10 Python
python json.dumps中文乱码问题解决
Apr 01 Python
用python进行视频剪辑
Nov 02 Python
Python中非常使用的6种基本变量的操作与技巧
Mar 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
全国FM电台频率大全 - 6 辽宁省
2020/03/11 无线电
php miniBB中文乱码问题解决方法
2008/11/25 PHP
PHP判断是否有Get参数的方法
2014/05/05 PHP
destoon复制新模块的方法
2014/06/21 PHP
学习php设计模式 php实现建造者模式
2015/12/07 PHP
如何判断php mysqli扩展类是否开启
2016/12/24 PHP
php语法检查的方法总结
2019/01/21 PHP
PHP5.5基于mysqli连接MySQL数据库和读取数据操作实例详解
2019/02/16 PHP
Centos7安装swoole扩展操作示例
2020/03/26 PHP
基于jquery的表格排序
2010/09/11 Javascript
Javascript 倒计时源代码.(时.分.秒) 详细注释版
2011/05/09 Javascript
60个很实用的jQuery代码开发技巧收集
2014/12/15 Javascript
前端性能优化及技巧
2016/05/06 Javascript
js获取客户端操作系统类型的方法【测试可用】
2016/05/27 Javascript
AngularJS操作键值对象类似java的hashmap(填坑小结)
2016/11/12 Javascript
如何实现json数据可视化详解
2016/11/24 Javascript
基于js实现的限制文本框只可以输入数字
2016/12/05 Javascript
node.js利用mongoose获取mongodb数据的格式化问题详解
2017/10/06 Javascript
js操作table中tr的顺序实现上移下移一行的效果
2018/11/22 Javascript
仿iPhone通讯录制作小程序自定义选择组件的实现
2019/05/23 Javascript
微信小程序左滑删除实现代码实例
2019/09/16 Javascript
解决vue项目中出现Invalid Host header的问题
2020/11/17 Javascript
python3图片转换二进制存入mysql
2013/12/06 Python
Python实现统计文本文件字数的方法
2017/05/05 Python
Python实现变量数值交换及判断数组是否含有某个元素的方法
2017/09/18 Python
python中dict字典的查询键值对 遍历 排序 创建 访问 更新 删除基础操作方法
2018/09/13 Python
python numpy数组中的复制知识解析
2020/02/03 Python
基于python实现MQTT发布订阅过程原理解析
2020/07/27 Python
html5指南-6.如何创建离线web应用程序实现离线访问
2013/01/07 HTML / CSS
来自圣地亚哥的实惠太阳镜:Knockaround
2018/08/27 全球购物
世界上最好的足球商店:Unisport
2019/03/02 全球购物
现在输入n个数字,以逗号,分开;然后可选择升或者降序排序;按提交键就在另一页面显示按什么排序,结果为,提供reset
2012/11/09 面试题
学校万圣节活动方案
2014/02/13 职场文书
环保倡议书500字
2014/05/15 职场文书
2014年销售员工作总结
2014/12/01 职场文书
使用Redis实现点赞取消点赞的详细代码
2022/03/20 Redis