2020.10.6 ThreadLocal
在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量要好,因为局部变量不会被其他线程改变。
但是局部变量也存在问题——在函数调用的时候,传递起来很麻烦:
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)
每个函数都要一层一层地传递最上层的局部变量。
解决方法:
ThreadLocal
import threading from Student import Student #创建全局ThreadLocal对象 local_school=threading.local() def process_student(): #获取当前线程关联的Student std=local_school.Student print('Hello ,%s (in %s)'%(std,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内部会自己处理。
另外,绑定的变量不一定必须是Student,也可以是Teacher……
ThreadLocal最常用的地方是为每一个线程绑定一个数据库连接,HTTP请求,用户身份信息,这样一个线程的所有调用到的处理函数都可以很方便地访问这些资源。