对于一些简单的线程相关代码,例如:
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相关的内容可以带来这样的结果。
+=
语句使用了不同数量的操作码,这意外地使其线程安全。 - Tin Tvrtkovića += 1
更改为a += int(1)
将会导致预期的较低数字再次出现。 - Kelly Bundy