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使用xlrd模块操作Excel数据导入的方法
May 26 Python
python3抓取中文网页的方法
Jul 28 Python
在Python中使用正则表达式的方法
Aug 13 Python
python 调用win32pai 操作cmd的方法
May 28 Python
pip命令无法使用的解决方法
Jun 12 Python
python简单验证码识别的实现方法
May 10 Python
Django处理多用户类型的方法介绍
May 18 Python
python实现文件的分割与合并
Aug 29 Python
python异步编程 使用yield from过程解析
Sep 25 Python
Django单元测试中Fixtures的使用方法
Feb 26 Python
Java爬虫技术框架之Heritrix框架详解
Jul 22 Python
python空元组在all中返回结果详解
Dec 15 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
ThinkPHP中实例Model方法的区别说明
2010/08/21 PHP
获取PHP警告错误信息的解决方法
2013/06/03 PHP
深入解析phpCB批量转换的代码示例
2013/06/27 PHP
如何使用php输出时间格式
2013/08/31 PHP
php项目中类的自动加载实例讲解
2019/09/12 PHP
JavaScript 面向对象之命名空间
2010/05/04 Javascript
js实现连续英文字符自动换行兼容ie6 ie7和firefox
2013/09/06 Javascript
jQuery获得包含margin的outerWidth和outerHeight的方法
2015/03/25 Javascript
jquery实现在网页指定区域显示自定义右键菜单效果
2015/08/25 Javascript
jquery实现的判断倒计时是否结束代码
2016/02/05 Javascript
微信小程序 教程之wxapp 视图容器 view
2016/10/19 Javascript
详解vue项目优化之按需加载组件-使用webpack require.ensure
2017/06/13 Javascript
JS实现多张图片预览同步上传功能
2017/06/23 Javascript
微信小程序自定义prompt组件步骤详解
2018/06/12 Javascript
Nodejs使用Mongodb存储与提供后端CRD服务详解
2018/09/04 NodeJs
vue+element+Java实现批量删除功能
2019/04/08 Javascript
JS实现网页时钟特效
2020/03/25 Javascript
Javascript如何递归遍历本地文件夹
2020/08/06 Javascript
Antd的Table组件嵌套Table以及选择框联动操作
2020/10/24 Javascript
[53:03]Optic vs TNC 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[51:29]完美世界DOTA2联赛循环赛 Matador vs Forest BO2第一场 11.05
2020/11/05 DOTA
Python生成数字图片代码分享
2017/10/31 Python
Python lambda函数基本用法实例分析
2018/03/16 Python
python 对key为时间的dict排序方法
2018/10/17 Python
关于ResNeXt网络的pytorch实现
2020/01/14 Python
Python3标准库之functools管理函数的工具详解
2020/02/27 Python
详解纯CSS3制作的20种loading动效
2017/07/05 HTML / CSS
小学二年级学生评语
2014/04/21 职场文书
优秀共产党员事迹材料
2014/12/18 职场文书
一个都不能少观后感
2015/06/04 职场文书
放假通知怎么写
2015/08/18 职场文书
教师读书活动心得体会
2016/01/14 职场文书
七年级语文教学反思
2016/03/03 职场文书
2019年个人工作总结范文
2019/03/25 职场文书
2019年员工旷工保证书!
2019/06/28 职场文书
vue组件vue-esign实现电子签名
2022/04/21 Vue.js