Python 3.13t 是官方首次提供的开箱即用实验性自由线程构建,通过细粒度锁、原子引用计数和分离式GC实现真正的多线程并行,但需手动启用且伴随同步风险与性能权衡。

python3.13t 不是“Python 3.13 默认就无 GIL”,而是官方首次提供开箱即用的实验性自由线程构建——它代表了 Python 并行能力的一次实质性突破,而非概念炒作。
为什么 python3.13t.exe 启动后 CPU 才真能跑满?
传统 python.exe(哪怕 3.13)仍默认启用 GIL:所有线程串行执行字节码,CPU 密集任务永远卡在单核。而 python3.13t.exe 在启动时已预置细粒度锁+原子引用计数+分离式 GC 上下文,无需额外参数就能让 threading.Thread 真正并行。
常见错误现象:
- 用
python.exe运行多线程计算脚本,任务管理器显示仅 1 个核心满载,其余闲置 - 误以为安装了 Python 3.13 就自动无 GIL,没注意安装包是否带 “free-threaded binaries” 标识
实操建议:
立即学习“Python免费学习笔记(深入)”;
- Windows 用户必须勾选安装向导里的 “free-threaded binaries (experimental)” 选项,否则得到的是普通解释器
- Linux/macOS 用户若从源码编译,需显式传入
--enable-free-threading,--disable-gil已被弃用 - 验证方式:运行
python3.13t -c "import _testcapi; print(_testcapi.is_gil_enabled())",输出False才算生效
threading 在无 GIL 下为何反而更危险?
GIL 曾是“隐式安全网”:即使你忘了加锁,全局状态读写也大概率不会崩。现在这层保护没了,list.append()、dict[key] = value、甚至 import 都可能触发竞态。
典型踩坑场景:
- 多个线程同时往同一个
list追加元素,结果丢失条目或抛MemoryError - 在子线程中动态修改
sys.path或重载模块,引发ImportError或对象状态不一致 - 用
threading.settrace()调试时,因细粒度锁调度导致 trace 回调顺序混乱
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 共享可变对象前,显式加
threading.Lock;对简单计数可用threading.local()避免争用 - 避免在线程中执行
import、del sys.modules[...]等影响解释器全局状态的操作 - 优先用
concurrent.futures.ThreadPoolExecutor管理线程生命周期,它内置了任务隔离与异常传播机制
哪些 C 扩展在 python3.13t 下会直接报错?
不是所有 C 扩展都兼容自由线程模式。只要扩展里做了以下任意操作,大概率崩溃或静默出错:
- 直接访问全局解释器状态字段(如
PyInterpreterState.eval_breaker) - 调用已被标记为废弃的 GIL API(如
PyEval_RestoreThread、PyGILState_Ensure) - 假设
PyObject*的引用计数操作是线程安全的(旧版 NumPy、旧 Cython 绑定常见)
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 运行前先检查扩展是否声明支持 free-threading:查看其
setup.py或 PyPI 页面是否标注Requires-Python: >=3.13t - 用
PYTHONDEVMODE=1 python3.13t -c "import numpy"启动,观察是否输出RuntimeWarning: PyGILState_Ensure() called... - 关键生产环境慎用未适配的扩展;临时方案是把计算逻辑封装进
multiprocessing子进程,由主进程协调
为什么说 “无 GIL” 不等于 “无同步开销”?
细粒度锁和原子操作本身有成本:dict 查找比 GIL 版本慢约 5–8%,list.append() 在高争用下延迟翻倍。这不是 bug,而是权衡。
性能敏感点:
- 高频小对象分配(如循环中创建大量
tuple)会触发更多 per-thread arena 切换 - 跨线程传递大对象(如
numpy.ndarray)仍需拷贝或显式内存映射,共享内存 ≠ 零拷贝 - GC 增量标记阶段会短暂暂停所有线程,虽比 GIL 全局停顿短,但不可忽略
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
perf record -e 'syscalls:sys_enter_mmap' python3.13t script.py观察系统调用热点 - 对纯计算密集型任务,优先用
threading+ 显式锁;对 I/O+计算混合任务,考虑asyncio.to_thread()拆分 - 不要盲目追求线程数 = CPU 核心数;在 E-core/超线程混合架构上,实测 12 线程常比 16 线程吞吐更高
真正难的不是让代码“跑起来”,而是判断哪段逻辑该加锁、哪段该拆进子进程、哪段干脆交给 Rust 写的无 GIL 扩展——这些决策没有银弹,只有反复压测和观测。


















