浅析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 相关文章推荐
Python虚拟环境virtualenv的安装与使用详解
May 28 Python
Python实现的基数排序算法原理与用法实例分析
Nov 23 Python
基于python内置函数与匿名函数详解
Jan 09 Python
python pandas消除空值和空格以及 Nan数据替换方法
Oct 30 Python
浅谈Python中的全局锁(GIL)问题
Jan 11 Python
python文件写入write()的操作
May 14 Python
python中dict使用方法详解
Jul 17 Python
python语音识别指南终极版(有这一篇足矣)
Sep 09 Python
python时间time模块处理大全
Oct 25 Python
python单例模式的应用场景实例讲解
Feb 24 Python
Pytest中skip skipif跳过用例详解
Jun 30 Python
Python tensorflow卷积神经Inception V3网络结构
May 06 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获取数组中某元素的位置及array_keys函数应用
2013/01/29 PHP
PHP开启opcache提升代码性能
2015/04/26 PHP
PHP7之Mongodb API使用详解
2015/12/26 PHP
PHP正则表达式过滤html标签属性(DEMO)
2016/05/04 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
PHP程序员简单的开展服务治理架构操作详解(一)
2020/05/14 PHP
JavaScript DOM 添加事件
2009/02/14 Javascript
Javascript 构造函数,公有,私有特权和静态成员定义方法
2009/11/30 Javascript
JS 实现导航栏悬停效果
2013/09/23 Javascript
一个简单的jQuery计算器实现了连续计算功能
2014/07/21 Javascript
JavaScript中的原型链prototype介绍
2014/12/30 Javascript
jQuery实现根据类型自动显示和隐藏表单
2015/03/18 Javascript
JavaScript作用域示例详解
2016/07/07 Javascript
Node.js配合node-http-proxy解决本地开发ajax跨域问题
2016/08/31 Javascript
详解关于react-redux中的connect用法介绍及原理解析
2017/09/11 Javascript
JavaScript闭包原理与用法实例分析
2018/08/10 Javascript
js实现拾色器插件(ColorPicker)
2020/05/21 Javascript
vue实现购物车列表
2020/06/30 Javascript
JS数组reduce()方法原理及使用技巧解析
2020/07/14 Javascript
JavaScript文档加载模式以及元素获取
2020/07/28 Javascript
跟老齐学Python之再深点,更懂list
2014/09/20 Python
Python unittest模块用法实例分析
2018/05/25 Python
python求解数组中两个字符串的最小距离
2018/09/27 Python
谈谈Python中的while循环语句
2019/03/10 Python
利用pyecharts实现地图可视化的例子
2019/08/12 Python
python画蝴蝶曲线图的实例
2019/11/21 Python
python判断字符串以什么结尾的实例方法
2020/09/18 Python
python+selenium自动化实战携带cookies模拟登陆微博
2021/01/19 Python
纽约的奢华内衣店:Journelle
2016/07/29 全球购物
初中校园之声广播稿
2014/01/15 职场文书
元宵晚会主持词
2014/03/25 职场文书
综合素质自我评价怎么写
2014/09/14 职场文书
2014年党的群众路线教育实践活动整改措施(个人版)
2014/09/25 职场文书
2014年档案管理工作总结
2014/11/17 职场文书
经理聘任证明
2015/03/02 职场文书
Python中OpenCV实现简单车牌字符切割
2021/06/11 Python