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局部赋值的规则
Mar 07 Python
Python程序设计入门(1)基本语法简介
Jun 13 Python
Python中给List添加元素的4种方法分享
Nov 28 Python
scrapy自定义pipeline类实现将采集数据保存到mongodb的方法
Apr 16 Python
Python算法应用实战之栈详解
Feb 04 Python
Python分支结构(switch)操作简介
Jan 17 Python
Python如何抓取天猫商品详细信息及交易记录
Feb 23 Python
Java与Python两大幸存者谁更胜一筹呢
Apr 12 Python
Python机器学习k-近邻算法(K Nearest Neighbor)实例详解
Jun 25 Python
Python学习笔记之函数的参数和返回值的使用
Nov 20 Python
无惧面试,带你搞懂python 装饰器
Aug 17 Python
python如何爬取动态网站
Sep 09 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
福利彩票幸运号码自动生成器
2006/10/09 PHP
PHP时间戳使用实例代码
2008/06/07 PHP
PHP中将网页导出为Word文档的代码
2012/05/25 PHP
php后台如何避免用户直接进入方法实例
2013/10/15 PHP
php实现将wav文件转换成图像文件并在页面中显示的方法
2015/04/21 PHP
详解WordPress开发中的get_post与get_posts函数使用
2016/01/04 PHP
PHP笛卡尔积实现原理及代码实例
2020/12/09 PHP
鼠标滑上去后图片放大浮出效果的js代码
2011/05/28 Javascript
从零学jquery之如何使用回调函数
2014/05/16 Javascript
D3.js中data(), enter() 和 exit()的问题详解
2015/08/17 Javascript
JS事件添加和移出的兼容写法示例
2016/06/20 Javascript
对Angular.js Controller如何进行单元测试
2016/10/25 Javascript
vue组件详解之使用slot分发内容
2018/04/09 Javascript
webpack4.x下babel的安装、配置及使用详解
2019/03/07 Javascript
微信小程序整合使用富文本编辑器的方法详解
2019/04/25 Javascript
nodejs提示:cross-device link not permitted, rename错误的解决方法
2019/06/10 NodeJs
[07:26]2015国际邀请赛第二日TOP10集锦
2015/08/06 DOTA
python数据结构之二叉树的遍历实例
2014/04/29 Python
wxpython中利用线程防止假死的实现方法
2014/08/11 Python
Python三元运算实现方法
2015/01/12 Python
Python中的赋值、浅拷贝、深拷贝介绍
2015/03/09 Python
利用Python生成文件md5校验值函数的方法
2017/01/10 Python
python 一个figure上显示多个图像的实例
2019/07/08 Python
python爬虫-模拟微博登录功能
2019/09/12 Python
简单了解python数组的基本操作
2019/11/26 Python
Python使用GitPython操作Git版本库的方法
2020/02/29 Python
Django模型中字段属性choice使用说明
2020/03/30 Python
解决pyinstaller 打包exe文件太大,用pipenv 缩小exe的问题
2020/07/13 Python
python读取xml文件方法解析
2020/08/04 Python
python 提高开发效率的5个小技巧
2020/10/19 Python
python压包的概念及实例详解
2021/02/17 Python
高级方案规划工程师岗位职责
2013/11/29 职场文书
涉密人员保密承诺书
2014/05/28 职场文书
html实现随机点名器的示例代码
2021/04/02 Javascript
如何使用Maxwell实时同步mysql数据
2021/04/08 MySQL
Java移除无效括号的方法实现
2021/08/07 Java/Android