Python循环创建线程时迭代变量状态共享问题如何解决?
问题原因
这是Python闭包的迟绑定特性导致的:循环内部定义的op函数引用了外层的迭代变量i,但Python不会在函数定义阶段就捕获i的当前值,只会等到op实际执行(也就是3秒后线程调度运行)时才会去查找i的取值。此时for循环已经执行完毕,i的值已经固定为最后一次迭代的9,所有线程拿到的都是同一个i,因此输出全为9。
解决方案
要实现每次迭代的状态隔离,核心是在每次循环定义线程任务的时候,就把当前的i值静态绑定到任务中,不要等到运行时再去取外层变量。常用的两种实现方式如下:
方案1:用函数默认参数捕获当前值
Python函数的默认参数会在函数定义阶段就完成计算绑定,刚好可以用来保存每次迭代的i副本:
import threading from time import sleep threads = [] for i in range(0,10): # 定义函数时添加默认参数local_i=i,直接绑定当前迭代的i值 def op(local_i=i): sleep(3) print(local_i) threads.append(threading.Thread(target = op)) for th in threads: th.start() for th in threads: th.join()
方案2:用functools.partial预绑定参数
partial可以提前把参数和目标函数绑定生成新的可调用对象,绑定时就会保存当前的i值:
import threading from time import sleep from functools import partial # 把op提到循环外定义即可 def op(local_i): sleep(3) print(local_i) threads = [] for i in range(0,10): # partial会把当前的i值绑定到op的入参上,生成独立的任务对象 threads.append(threading.Thread(target = partial(op, local_i=i))) for th in threads: th.start() for th in threads: th.join()
两种方案都可以正确输出0到9的数值,输出顺序可能因为线程调度不一致,但不会再出现全为9的问题。
内容的提问来源于stack exchange,提问作者tmn
相关产品推荐
相关产品推荐

