对于一些简单的线程相关代码,例如:
import threading
a = 0
threads = []
def x():
global a
for i in range(1_000_000):
a += 1
for _ in range(10):
thread = threading.Thread(target=x)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
print(a)
assert a == 10_000_000
基于Python版本,我们得到了不同的行为。
对于3.10,输出为:
❯ python3.10 b.py
10000000
对于3.9,输出为:
❯ python3.9 b.py
2440951
Traceback (most recent call last):
File "/Users/romka/t/threads-test/b.py", line 24, in <module>
assert a == 10_000_000
AssertionError
由于我们没有获得任何锁定,对我来说,3.9的结果是显而易见的,也是意料之中的。问题是3.10为什么以及如何得到";正确的";结果,而不应该?
我正在审查Python 3.10的变更日志,没有任何与线程或GIL相关的东西可以带来这样的结果。
核心开发人员的回答:
Mark Shannon重构快速操作码调度的意外结果:https://github.com/python/cpython/commit/4958f5d69dd2bf86866c43491caf72f774ddec97—INPLACE_ADD操作码不再使用";"慢";检查中断等的调度路径。