浅析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 相关文章推荐
Python3中的列表,元组,字典,字符串相关知识小结
Nov 10 Python
Python文本特征抽取与向量化算法学习
Dec 22 Python
Python cookbook(数据结构与算法)将名称映射到序列元素中的方法
Mar 22 Python
Python线程同步的实现代码
Oct 03 Python
python中的tcp示例详解
Dec 09 Python
Python中判断子串存在的性能比较及分析总结
Jun 23 Python
python实现函数极小值
Jul 10 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
Jan 04 Python
基于python实现模拟数据结构模型
Jun 12 Python
python 数据类型强制转换的总结
Jan 25 Python
python 中 .py文件 转 .pyd文件的操作
Mar 04 Python
解决Pytorch dataloader时报错每个tensor维度不一样的问题
May 28 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入门学习知识点五 关于php数组的几个基本操作
2011/07/14 PHP
深入掌握include_once与require_once的区别
2013/06/17 PHP
PHP设计模式之观察者模式实例
2016/02/22 PHP
WAF的正确bypass
2017/01/05 PHP
php 开发中加密的几种方法总结
2017/03/22 PHP
laravel自定义分页效果
2017/07/23 PHP
Javascript原型链和原型的一个误区
2014/10/22 Javascript
jQuery实现的进度条效果
2015/07/15 Javascript
简单学习JavaScript中的for语句循环结构
2015/11/10 Javascript
js简单判断移动端系统的方法
2016/02/25 Javascript
JavaScript判断浏览器及其版本信息
2017/01/20 Javascript
Vue响应式原理详解
2017/04/18 Javascript
JS仿淘宝搜索框用户输入事件的实现
2017/06/19 Javascript
node+vue实现用户注册和头像上传的实例代码
2017/07/20 Javascript
对 Vue-Router 进行单元测试的方法
2018/11/05 Javascript
使用express来代理服务的方法
2019/06/21 Javascript
浅谈JS中几种轻松处理'this'指向方式
2019/09/16 Javascript
[02:02]2018DOTA2亚洲邀请赛Mineski赛前采访
2018/04/04 DOTA
深入剖析Python的爬虫框架Scrapy的结构与运作流程
2016/01/20 Python
Python优化技巧之利用ctypes提高执行速度
2016/09/11 Python
python多线程之事件Event的使用详解
2018/04/27 Python
Python基于机器学习方法实现的电影推荐系统实例详解
2019/06/25 Python
python文字转语音实现过程解析
2019/11/12 Python
基于python实现语音录入识别代码实例
2020/01/17 Python
python GUI库图形界面开发之PyQt5打开保存对话框QFileDialog详细使用方法与实例
2020/02/27 Python
Python读取多列数据以及用matplotlib制作图表方法实例
2020/09/23 Python
python破解同事的压缩包密码
2020/10/14 Python
python给list排序的简单方法
2020/12/10 Python
python实现三种随机请求头方式
2021/01/05 Python
Banana Republic英国官网:香蕉共和国,GAP集团旗下偏贵族风
2018/04/24 全球购物
诚信承诺书模板
2014/05/26 职场文书
小学生美德少年事迹材料
2014/08/24 职场文书
承德避暑山庄导游词
2015/02/03 职场文书
优秀共产党员事迹材料2016
2016/02/29 职场文书
MySQL 视图(View)原理解析
2021/05/19 MySQL
python 实现体质指数BMI计算
2021/05/26 Python