浅析Python多线程下的变量问题


Posted in Python onApril 28, 2015

在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。

但是局部变量也有问题,就是在函数调用的时候,传递起来很麻烦:

def process_student(name):
  std = Student(name)
  # std是局部变量,但是每个函数都要用它,因此必须传进去:
  do_task_1(std)
  do_task_2(std)

def do_task_1(std):
  do_subtask_1(std)
  do_subtask_2(std)

def do_task_2(std):
  do_subtask_2(std)
  do_subtask_2(std)

每个函数一层一层调用都这么传参数那还得了?用全局变量?也不行,因为每个线程处理不同的Student对象,不能共享。

如果用一个全局dict存放所有的Student对象,然后以thread自身作为key获得线程对应的Student对象如何?

global_dict = {}

def std_thread(name):
  std = Student(name)
  # 把std放到全局变量global_dict中:
  global_dict[threading.current_thread()] = std
  do_task_1()
  do_task_2()

def do_task_1():
  # 不传入std,而是根据当前线程查找:
  std = global_dict[threading.current_thread()]
  ...

def do_task_2():
  # 任何函数都可以查找出当前线程的std变量:
  std = global_dict[threading.current_thread()]
  ...

这种方式理论上是可行的,它最大的优点是消除了std对象在每层函数中的传递问题,但是,每个函数获取std的代码有点丑。

有没有更简单的方式?

ThreadLocal应运而生,不用查找dict,ThreadLocal帮你自动做这件事:

import threading

# 创建全局ThreadLocal对象:
local_school = threading.local()

def process_student():
  print 'Hello, %s (in %s)' % (local_school.student, threading.current_thread().name)

def process_thread(name):
  # 绑定ThreadLocal的student:
  local_school.student = name
  process_student()

t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()

执行结果:

Hello, Alice (in Thread-A)
Hello, Bob (in Thread-B)

全局变量local_school就是一个ThreadLocal对象,每个Thread对它都可以读写student属性,但互不影响。你可以把local_school看成全局变量,但每个属性如local_school.student都是线程的局部变量,可以任意读写而互不干扰,也不用管理锁的问题,ThreadLocal内部会处理。

可以理解为全局变量local_school是一个dict,不但可以用local_school.student,还可以绑定其他变量,如local_school.teacher等等。

ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。

Python 相关文章推荐
在Windows8上的搭建Python和Django环境
Jul 03 Python
python读写ini配置文件方法实例分析
Jun 30 Python
Python基于Floyd算法求解最短路径距离问题实例详解
May 16 Python
python skimage 连通性区域检测方法
Jun 21 Python
Python考拉兹猜想输出序列代码实践
Jul 05 Python
Python 画出来六维图
Jul 26 Python
wxpython绘制音频效果
Nov 18 Python
python飞机大战pygame游戏之敌机出场实现方法详解
Dec 17 Python
利用Pytorch实现简单的线性回归算法
Jan 15 Python
Django多数据库配置及逆向生成model教程
Mar 28 Python
Scrapy中如何向Spider传入参数的方法实现
Sep 28 Python
详解python中的异常捕获
Dec 15 Python
python实现向ppt文件里插入新幻灯片页面的方法
Apr 28 #Python
Python实现对PPT文件进行截图操作的方法
Apr 28 #Python
在Python下尝试多线程编程
Apr 28 #Python
Python输出PowerPoint(ppt)文件中全部文字信息的方法
Apr 28 #Python
python使用append合并两个数组的方法
Apr 28 #Python
python实现的简单文本类游戏实例
Apr 28 #Python
初步解析Python下的多进程编程
Apr 28 #Python
You might like
PHP中date()日期函数有关参数整理
2011/07/19 PHP
PHP实现图片旋转效果实例代码
2014/10/01 PHP
php上传文件并存储到mysql数据库的方法
2015/03/16 PHP
php in_array() 检查数组中是否存在某个值详解
2016/11/23 PHP
js window.onload 加载多个函数的方法
2009/11/02 Javascript
Jquery节点遍历next与nextAll方法使用示例
2014/07/22 Javascript
JS实现5秒钟自动封锁div层的方法
2015/02/20 Javascript
JS去除重复并统计数量的实现方法
2016/12/15 Javascript
JS中with的替代方法与String中的正则方法详解
2016/12/23 Javascript
浅谈vue自定义全局组件并通过全局方法 Vue.use() 使用该组件
2017/12/07 Javascript
在微信小程序中保存网络图片
2019/02/12 Javascript
jquery 验证用户名是否重复代码实例
2019/05/14 jQuery
详解django模板与vue.js冲突问题
2019/07/07 Javascript
简单谈谈offsetleft、offsetTop和offsetParent
2020/12/04 Javascript
NestJs使用Mongoose对MongoDB操作的方法
2021/02/22 Javascript
利用 Chrome Dev Tools 进行页面性能分析的步骤说明(前端性能优化)
2021/02/24 Javascript
[05:36]DOTA2 2015国际邀请赛中国区预选赛第四日TOP10
2015/05/29 DOTA
Python正则表达式使用范例分享
2016/12/04 Python
python读写json文件的简单实现
2017/04/11 Python
解决出现Incorrect integer value: '' for column 'id' at row 1的问题
2017/10/29 Python
Python学习pygal绘制线图代码分享
2017/12/09 Python
Python Numpy 数组的初始化和基本操作
2018/03/13 Python
如何使用 Pylint 来规范 Python 代码风格(来自IBM)
2018/04/06 Python
Python实现生成密码字典的方法示例
2019/09/02 Python
python图形界面开发之wxPython树控件使用方法详解
2020/02/24 Python
快速解决pymongo操作mongodb的时区问题
2020/12/05 Python
CSS3实现的渐变幻灯片效果
2020/12/07 HTML / CSS
关于HTML5的22个初级技巧(图文教程)
2012/06/21 HTML / CSS
美国艺术和工艺品商店:Hobby Lobby
2020/12/09 全球购物
.net软件工程师面试题
2015/03/31 面试题
初一生物教学反思
2014/01/18 职场文书
奥利奥广告词
2014/03/20 职场文书
大学新闻系应届生求职信
2014/06/02 职场文书
党员群众路线学习心得体会
2014/11/04 职场文书
你真的会用Mysql的explain吗
2022/03/31 MySQL
KVM基础命令详解
2022/04/30 Servers