Python 3.13t 首次实现 threading.Thread 在 CPU 密集型任务中真正跑满多核,需显式启用无 GIL 模式并验证 sys._is_gil_enabled() 为 False,否则仍受 GIL 限制。

python3.13t 能让 threading.Thread 在 CPU 密集型任务中真正跑满多核——不是“理论上可以”,而是你 top 一眼就能看到所有核心同时活跃,这是 Python 自诞生以来第一次。
怎么确认你真在用无GIL解释器?
装完 Python 3.13 不等于自动无 GIL。Windows 用户必须在安装时勾选 “free-threaded binaries (experimental)”;Linux/macOS 用户需从源码编译并传 --enable-free-threading。验证方式只有一条:python3.13t -c "import sys; print(sys._is_gil_enabled())" 输出 False 才算生效。
常见错误:误用 python.exe 或 python3.13 启动脚本,结果还是带 GIL 的老行为;PYTHONNOGIL=1 环境变量对标准构建无效,不能“热开启”。
为什么 dict/list 并发写入不一定安全?
无 GIL 后,dict 和 list 改用 per-object 锁,单个对象的 d[k] = v 或 l.append(x) 通常没问题,但以下场景仍会出错:
- 多线程遍历并修改同一 dict(如 for k in d: d[k] *= 2)触发 RuntimeError: dictionary changed size during iteration
- 多个线程分别往不同 dict 写,再用 update() 合并——合并操作本身不加锁,可能丢数据
- 共享计数器用 counter += 1,没加 threading.Lock 或用 _thread._atomic,结果少计数
根本原因:细粒度锁只保单对象原子性,不保跨操作逻辑一致性。
哪些 C 扩展大概率崩溃?
只要 C 扩展代码里做了以下任意一项,python3.13t 下就可能段错误或静默错:
- 直接读写 PyInterpreterState 字段(比如 eval_breaker)
- 调用已废弃的 GIL API,如 PyEval_RestoreThread、PyGILState_Ensure
- 假设 Py_INCREF/Py_DECREF 是线程安全的(旧版 pandas、未更新的 Cython 绑定常见)
实测中,import pandas 在 python3.13t 下直接失败;numpy 基础数组运算可用,但 np.einsum 或某些 ufunc 可能返回错误结果;cv2、pyarrow 默认持 GIL,反而会阻塞其他线程。
单线程变慢是设计代价,不是 bug
启用无 GIL 后,纯 Python 单线程性能平均下降 5%–15%,尤其在高频创建/销毁小对象(如列表推导、字典构造)时更明显。这不是优化不到位,而是原子操作开销、per-object 锁管理、mimalloc 分配器的线程本地缓存等机制必然带来的成本。Web API 响应时间从 200ms 升至 380ms 的案例,就是典型体现。别指望“又快又稳”,它解决的是“能不能并行”,不是“单线程能不能更快”。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
真正难的不是跑起来,是判断你的代码里有没有隐式依赖 GIL 的地方——比如某个第三方库的文档没提线程安全,但它的 C 层其实靠 GIL 隐式串行化了;或者你写的 import 动态加载逻辑,在无 GIL 下多个线程同时触发,引发 ImportError 或模块状态错乱。这些坑不会报错,只会让你的结果偶尔不对。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










