You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu环境下Python多线程无竞态条件,如何禁用GIL?

为什么Python多线程脚本未触发竞态条件,且GIL如何禁用?

我在Ubuntu 22.04 LTS机器上运行未加锁的Python脚本时,始终得到相同的输出,无法理解为什么没有发生线程切换从而引发竞态条件。

from threading import *

lock = Lock()
count = 0

def task():
    global count
    for i in range(1000000):
        count += 1;

if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task)

    t1.start()
    t2.start()

    t1.join()
    t2.join()

    print(count)

上述代码始终输出一致的结果2000000。

执行命令dmidecode -t processor|grep Count -的输出为:

Core Count: 4
Thread Count: 8

执行命令cat /sys/devices/system/cpu/smt/control的输出为:

on

我通过终端执行该Python脚本:python3 file.py。

补充内容

def check_single_threaded():
    active_threads = active_count()
    return active_threads == 1

该函数返回True。经进一步研究发现,这是由于Global Interpreter Lock(GIL)仅允许单个线程运行,请问有什么方法可以禁用它?


问题原因解析

  1. GIL调度逻辑:CPython的GIL会在执行一定数量的字节码(默认100条)或遇到I/O操作时释放,让其他线程有机会执行。但你的count += 1操作虽然在字节码层面是三步(读值、加1、写回),但循环内的操作过于简单快速,线程可能在GIL触发切换前就完成了整个100万次循环,导致两个线程完全串行执行,自然不会出现竞态条件。
  2. active_count()的使用误区:你在主线程调用这个函数时,可能子线程还未启动或已经执行完毕,所以返回1。如果把这个函数放到task()内部执行,就能看到正确的活跃线程数量。

禁用GIL的可行方案

CPython本身无法直接禁用GIL,但可以通过以下方式绕过GIL限制:

  • 改用多进程:使用multiprocessing模块,每个进程拥有独立的Python解释器和内存空间,完全不受GIL约束,适合CPU密集型任务。
  • 使用无GIL的Python实现:比如PyPy(对CPU密集型任务优化好,部分场景自动规避GIL)、Jython(基于JVM实现,无GIL)、IronPython(基于.NET平台,无GIL)。
  • 借助C扩展或第三方库:像numpy、numba这类库的核心逻辑在C层面执行,执行时会自动释放GIL;也可以自行编写C扩展,在关键代码段手动释放GIL。
  • 升级到Python 3.12+:新版本CPython对GIL做了大幅优化,多核场景下线程切换效率更高,但仍未完全移除GIL。

内容的提问来源于stack exchange,提问作者Kevin Martin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 22:14:57