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

使用ThreadPoolExecutor运行两个共享全局变量的阻塞函数出现死锁,如何修复实现异步交替执行?

问题根因

两个关键错误直接导致了当前的运行结果和伪“死锁”表现:

  • 线程池传参方式完全错误,根本没实现并发:你调用executor.submit()时给函数名加了括号,相当于先在主线程同步执行incA()这个无限循环,等incA()因为检测到q键触发break完全跑完,才会走到下一行代码执行printA(),等printA()也在主线程跑完,才会把两个函数返回的None值丢给线程池。线程池拿到不可执行的None,自然会卡在等待状态,你看到的前面一长串inc日志、最后一行print日志,完全是主线程串行跑两个函数的结果,根本没进入子线程并发执行。
  • 无让出的高速循环导致调度完全不可控:就算修正传参问题,两个没有任何暂停的死循环会一直占满CPU,Python的GIL调度会随机让某个线程连续跑成百上千次才切给另一个,根本无法实现稳定的交替输出效果。
分步修复方案
  1. 修正submit的传参写法
    把函数引用本身传给submit,不要加括号触发主线程同步执行:

    # 错误写法:会先在主线程直接执行函数,再把返回值传给线程池
    # f1 = executor.submit(incA())
    # f2 = executor.submit(printA())
    
    # 正确写法:把函数对象传入,由线程池在子线程中调用执行
    f1 = executor.submit(incA)
    f2 = executor.submit(printA)
    
  2. 在每个循环中添加微小延迟,主动让出CPU
    导入time模块,在两个函数的循环内部加1毫秒左右的暂停,不让单个线程一直占用GIL,给调度器机会交替切换执行权,输出自然会形成自然交替的节奏:

    import time
    
    def incA():
        global a
        while True:
            print(f'inc a: {a} -> {a+1}')
            a += 1
            time.sleep(0.001)  # 主动让出CPU
            if keyboard.is_pressed('q'):
                break
    
    def printA():
        while True:
            print(f'print a: {a}')
            time.sleep(0.001)  # 主动让出CPU
            if keyboard.is_pressed('q'):
                break
    
  3. (可选)严格1:1交替的输出控制
    如果需要完全严格的交替顺序(避免调度随机导致的偶尔连续多次输出同一个函数的日志),可以加全局状态标志做顺序控制:

    # 全局执行权限标志
    can_inc = True
    
    def incA():
        global a, can_inc
        while True:
            if can_inc:
                print(f'inc a: {a} -> {a+1}')
                a += 1
                can_inc = False  # 执行完inc,把权限交给print函数
            time.sleep(0.001)
            if keyboard.is_pressed('q'):
                break
    
    def printA():
        global a, can_inc
        while True:
            if not can_inc:
                print(f'print a: {a}')
                can_inc = True  # 执行完print,把权限交回inc函数
            time.sleep(0.001)
            if keyboard.is_pressed('q'):
                break
    
修复后的运行效果

修正传参、添加CPU让出延迟后,两个函数会在独立子线程并发运行,控制台会按照预期节奏交替输出inc和print的日志,按下q键可以正常触发两个线程退出,不会出现主线程串行运行、程序卡在等待的伪死锁问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 09:45:04