当前位置: 首页 > 编程笔记 >

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

司徒耀
2023-03-14
本文向大家介绍浅析Python多线程下的变量问题,包括了浅析Python多线程下的变量问题的使用技巧和注意事项,需要的朋友参考一下

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

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

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请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。

 类似资料:
  • 如何从多个线程同时访问静态变量。 如果我有这样的课 我需要访问线程1的值,比如 从线程2中,我需要设置如下值 这会导致内存冲突吗?。如果是,建议使用什么方法来处理这种情况?。

  • 我有一个很大的json文件,其中包含一个很长的信息列表,我需要在许多子线程中只读该列表。 在java中,我们可以只通过值而不是引用来传递变量,我希望在内存/磁盘使用方面尽可能减少我的程序。 现在我将完整的列表或它的子列表传递给我创建的每个线程。 有没有一种方法可以从所有线程访问相同的列表变量,而不将完整的列表复制到每个线程中? 我需要“只读取”列表 下面是我的程序是如何工作的 1-服务(等待文件创

  • 本文向大家介绍iOS多线程开发——NSThread浅析,包括了iOS多线程开发——NSThread浅析的使用技巧和注意事项,需要的朋友参考一下   在iOS开发中,多线程的实现方式主要有三种,NSThread、NSOperation和GCD,我前面博客中对NSOperation和GCD有了较为详细的实现,为了学习的完整性,今天我们主要从代码层面来实现NSThread的使用。案例代码上传至 http

  • 我正在研究哲学家进餐问题,n位哲学家轮流思考和进餐。我想有一个版本,哲学家们会按照id的顺序进食:0,1,2,3,4。。。,但是我的线程一直被阻塞。我的线程从调用PhilosopherThread开始。 我想把哲学家们整理好有点麻烦。我只能在线程堵塞之前吃前2个线程。 编辑:据我所知,我这样做是对的。我首先锁定互斥锁,然后检查pindex是否是当前线程id,如果不是,线程将等待,直到pindex等

  • 本文向大家介绍浅析JavaScript声明变量,包括了浅析JavaScript声明变量的使用技巧和注意事项,需要的朋友参考一下 JavaScript的变量声明语句无论出现在何处,都会先于其他代码首先被执行。使用var关键词声明变量的作用域是当前的执行上下文,有可能是外围函数,或者,当变量声明在函数体之外时,则为全局变量。 定义在函数体外的都属于全局变量,定义在函数体内的属于局部变量。这里的定义是指

  • 我正在学习Java的易失性,我的代码是这样的。 我知道如果flag没有volatile,线程就不会存在。这是能见度的问题。 但是,如果我在while循环中编写一些代码,如,t1线程将读取新值并停止循环。 我知道如何使用volatile来解决可见性问题,所以我的问题是: 为什么当我写?