Python多线程中target传函数名与带括号的差异及原因咨询
Python多线程中target传参差异的原因分析
问题场景
在学习Python多线程的**竞态条件(race condition)和锁(lock)**概念时,遇到一个特殊现象:
测试代码如下:
from threading import Thread import time value = 0 def increase(): global value local = value local += 1 time.sleep(0.1) value = local print('start value', value) #create threads thread1 = Thread(target=increase) thread2 = Thread(target=increase) #start threads thread1.start() thread2.start() #join threads thread1.join() thread2.join() print('end value', value) print('end main')
两种传参方式的执行结果
- target传入函数名
increase(不带括号)
执行结果:
start value 0 end value 1 end main
这是竞态条件下的正常结果。
- target传入
increase()(带括号)
执行结果:
start value 0 end value 2 end main
未使用锁却得到了类似加锁的结果,这一现象的原因是什么?
原因解析
核心问题在于Thread类的target参数的作用逻辑:
- 当传入
increase(不带括号)时,你传递的是函数对象,线程启动后会自动调用这个函数。此时两个线程并发执行increase,触发竞态条件:两个线程都先读取到value=0,各自加1后休眠,最后先后把value设为1,最终结果为1。 - 当传入
increase()(带括号)时,你传递的不是函数,而是立即在主线程中执行increase()后的返回值(此处为None)。线程启动后,由于target是None,不会执行任何有效逻辑。
最终value=2的原因是:创建线程对象时,你已经在主线程里顺序执行了两次increase():
thread1 = Thread(target=increase()) # 主线程执行一次increase,value变为1 thread2 = Thread(target=increase()) # 主线程再执行一次increase,value变为2
后续启动的两个线程并未参与value的修改,所以最终结果是主线程两次调用后的2,和多线程并发毫无关系。
简单来说,带括号的写法根本没用到多线程并发,只是在主线程里顺序执行了两次函数,自然不会出现竞态条件。
内容的提问来源于stack exchange,提问作者Anmol Virk
相关产品推荐
相关产品推荐

