Python多线程学习(三)

344 阅读2分钟

ThreadLocal

在多线程情况下,每个线程的局部变量只有自己能看到,线程之间不会影响,但是局部变量在函数调用的时候传递很麻烦。

案例:

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

def t1(std):
    t2(std)
    t3(std)
    
def t2(std):
    t4(std)
    t5(std)

每个函数一层一层调用都按照这种方式传参很繁琐冗余。用全局变量也不行,因为每个线程处理不同的 Student 对象,无法共享。

可以想到用一个全局变量 dict 存放所有的 Student 对象,然后以 thread 自身作为 key 获得线程对应的 Student 对象。

实战( Python3 )

d = {}

def std_thread(name):
    std = Student(name)
    # 把 std 放到全局变量 d 中:
    d[threading.current_thread()] = std
    t1()
    t2()
    
def t1():
    # 不传入 std ,而是根据当前线程查找:
    std = d[threading.current_thread()]
    ...
    
def t2():
    # 任何函数都可以查找出当前线程的std变量:
    std = d[threading.current_thread()]
    ...

这种方式最大的优点是消除了 std 对象在每层函数中的传递问题,代码有点丑。在这种情况下 ThreadLocal 应运而生,不用查找 dictThreadLocal 帮你自动做这件事。

实战( Python3 )

import threading
    
# 创建全局 ThreadLocal 对象:
tl = threading.local()
def process():
    # 获取当前线程关联的 student:
    name = tl.student
    print('Hello, %s (in %s)' % (name, threading.current_thread().name))
    
def task(name):
    # 绑定 ThreadLocal 的 student :
    tl.student = name
    process()
    
t1 = threading.Thread(target= task, args=('sam',), name='t1')
t2 = threading.Thread(target= task, args=('echo',), name='t2')
t1.start()
t2.start()
t1.join()
t2.join()   

运行结果:

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

  • 一个 ThreadLocal 变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰也不用管理锁的问题,ThreadLocal 内部会处理。。ThreadLocal 解决了参数在一个线程中各个函数之间互相传递的问题。

本文参考:

廖雪峰:www.liaoxuefeng.com/wiki/101695…

希望看客老爷打赏些买西瓜钱

支付宝

支付宝

微信

微信