python 多线程 threading.local
threading.local 是一个全局变量,作用在线程(主线程和子线程适用)中,目的是在每个线程中私有一份空间存放自己私有的变量。
用法:
import threading import time from concurrent.futures import ThreadPoolExecutor v = threading.local() lock = threading.RLock() def func(arg): v.phone = arg time.sleep(2) lock.acquire() print(arg, v.phone) lock.release() p = ThreadPoolExecutor(3) for i in range(30): p.submit(func, i)
以上代码的每个线程中都有一个v.phone且值都是隔离独立的。
模拟实现:
import threading import time class Local(object): info = {} def __getattr__(self, item): ident = threading.get_ident() return self.info[ident][item] def __setattr__(self, key, value): ident = threading.get_ident() if ident in self.info: self.info[ident][key] = value else: self.info[ident] = {key:value} obj = Local() lock = threading.RLock() def func(args): obj.num1 = args # 子进程设置私有变量 time.sleep(2) t_name = threading.current_thread().getName() lock.acquire() print('线程%s的num1:'%t_name, obj.num1) lock.release() for i in range(10): t = threading.Thread(target=func, args=(i,)) t.setName(str(i)) t.start() obj.num1 = 100 # 主线程设置自己的私有变量 print('主线程的num1:', obj.num1)
上面代码中定义的类在实例化时,创建了一个字典,当在线程中使用obj.num1 = arg进行赋值时,会调用对象的__setattr__方法,将线程的id作为key,num:key的键值对作为value来填充这个字典,而使用obj.num1获取值时则是调用对象的__getattr__方法,会获取当前线程的id,然后通过id找到对应的子字典,在子字典中通过key num1找到对应的值。