为何Python全局变量未出现竞态条件?如何复现该问题?
问题分析与解决
为什么没出现竞态条件?
你的代码里存在一个关键的变量作用域错误:
adder和subtractor函数通过global value声明,操作的是全局的value- 但
main函数里定义了局部变量value = 0,最后打印的是这个局部变量,和线程操作的全局变量是完全独立的两个变量
所以不管线程怎么修改全局value,你打印的始终是main里初始化的局部0,自然看不到竞态条件的结果。
如何复现竞态条件?
只需要删掉main函数里的value = 0,让main打印全局的value即可:
from threading import Thread, Lock value = 0 def adder(amount, repeats): global value for _ in range(repeats): value += amount def subtractor(amount, repeats): global value for _ in range(repeats): value -= amount def main(): # 移除局部变量声明 adder_thread = Thread(target=adder, args=(100, 1000000)) subtractor_thread = Thread(target=subtractor, args=(100, 1000000)) subtractor_thread.start() adder_thread.start() print('Waiting for threads to finish...') adder_thread.join() subtractor_thread.join() print(f'Value: {value}') if __name__ == '__main__': main()
运行修改后的代码,你会发现打印的value是随机的非零值——这就是竞态条件的结果:value += amount和value -= amount本质是读取-修改-写入三步操作,多线程下这些步骤会被打断,导致最终值偏离预期。
全局变量是否被同步原语保护?
没有。你的代码虽然导入了Lock,但完全没有用它来保护对全局value的访问,线程对value的操作完全无同步,这正是竞态条件产生的原因。
如果要解决竞态条件,可以用Lock包裹临界区代码:
from threading import Thread, Lock value = 0 lock = Lock() def adder(amount, repeats): global value for _ in range(repeats): with lock: value += amount def subtractor(amount, repeats): global value for _ in range(repeats): with lock: value -= amount def main(): adder_thread = Thread(target=adder, args=(100, 1000000)) subtractor_thread = Thread(target=subtractor, args=(100, 1000000)) subtractor_thread.start() adder_thread.start() print('Waiting for threads to finish...') adder_thread.join() subtractor_thread.join() print(f'Value: {value}') if __name__ == '__main__': main()
这样每次只有一个线程能执行value的修改操作,最终结果会稳定为0。
内容的提问来源于stack exchange,提问作者Oleg
相关产品推荐
相关产品推荐

