Python threading.local使用getattr赋值返回非预期结果问题咨询
问题原因分析
这不是getattr本身的问题,也和线程安全无关,核心原因是ThreadPoolExecutor的工作线程复用机制,加上代码逻辑本身的设计问题:
threading.local()的属性是线程隔离的,主线程设置的threadLocal.x在子线程中默认不存在,不同线程的属性值互不干扰。- ThreadPoolExecutor并不会为每一个任务都创建全新的线程,而是会优先复用已有的空闲工作线程:你写的
f函数执行速度极快,当第一个参数为0的任务执行完成后,线程处于空闲状态,后续的4个任务都会复用这同一个工作线程执行。 - 你写的
getattr(threadLocal, 'x', x)逻辑是:如果当前线程的threadLocal已经存在属性x,就直接取已有值,只有不存在时才会用参数x作为默认值:- 第一个任务执行时,线程里没有
x属性,所以取默认值0,给当前线程的threadLocal.x赋值为0,返回0。 - 后续4个任务复用同一个线程时,线程的
threadLocal.x已经是0了,所以getattr永远返回已有的0,不会用传入的参数1/2/3/4,最终输出全是0。
- 第一个任务执行时,线程里没有
验证方法
你可以在f函数中打印当前线程ID,就能看到所有任务都使用了同一个线程:
import threading def f(x): print(threading.get_ident()) # 新增这行,会发现打印的ID全相同 threadLocal.x = getattr(threadLocal, 'x', x) return threadLocal.x
如果要得到预期输出,要么直接用注释里的直接赋值逻辑threadLocal.x = x,要么在f里加短时间睡眠强制线程池创建新线程(仅用于验证,生产环境不要这么写)。
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

