Python 3.10 和其他版本的线程差异

Zad*_*org 28 python multithreading python-multithreading python-internals

对于一些简单的线程相关代码,即:

\n
import threading\n\n\na = 0\nthreads = []\n\n\ndef x():\n    global a\n    for i in range(1_000_000):\n        a += 1\n\n\nfor _ in range(10):\n    thread = threading.Thread(target=x)\n    threads.append(thread)\n    thread.start()\n\n\nfor thread in threads:\n    thread.join()\n\n\nprint(a)\nassert a == 10_000_000\n
Run Code Online (Sandbox Code Playgroud)\n

根据 Python 版本,我们得到了不同的行为。

\n

对于 3.10,输出为:

\n
\xe2\x9d\xaf python3.10 b.py\n10000000\n
Run Code Online (Sandbox Code Playgroud)\n

对于 3.9,输出为:

\n
\xe2\x9d\xaf python3.9 b.py\n2440951\nTraceback (most recent call last):\n  File "/Users/romka/t/threads-test/b.py", line 24, in <module>\n    assert a == 10_000_000\nAssertionError\n
Run Code Online (Sandbox Code Playgroud)\n

由于我们没有获取任何锁,对我来说,3.9 的结果是显而易见的并且是预期的。问题是为什么 3.10 得到了“正确”的结果,而不应该得到“正确”的结果?

\n

我正在查看 Python 3.10 的变更日志,没有任何与线程或 GIL 相关的内容可以带来这样的结果。

\n

Ned*_*der 25

核心开发人员的回答

Mark Shannon 重构快速操作码调度的更改的意外后果:https://github.com/python/cpython/commit/4958f5d69dd2bf86866c43491caf72f774ddec97 - INPLACE_ADD 操作码不再使用检查中断等的“慢速”调度路径。