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

多线程i +=1在Windows与Linux上的行为差异原因探究

为什么Python多线程i += 1在Windows和Linux表现不同?

首先明确:i += 1确实不是原子操作,它拆解为三个独立步骤:读取当前i的值、计算i+1、将结果写回i。多线程环境下,多个线程同时执行这三步会出现竞态条件,理论上最终结果应该小于预期的BASE*10。你遇到的Windows和Linux表现差异,不是巧合,是CPython在不同系统上的GIL(全局解释器锁)调度策略差异导致的。

核心原因:GIL的跨平台行为差异

CPython的多线程受GIL限制,同一时刻只有一个线程能执行Python字节码,但不同系统上GIL的释放逻辑不同:

  • Linux环境:CPython默认每执行100条字节码指令就主动释放GIL,让其他线程有机会抢占执行。这意味着你的test函数循环中,i +=1的操作会频繁被打断——线程A刚读取i的值,还没来得及写回,GIL就被释放,线程B读取了同一个i值,加1后写回,导致线程A的写回操作覆盖了线程B的结果,最终i的增量大量丢失。
  • Windows环境:GIL的释放不依赖字节码计数,而是等待系统的线程调度信号(比如时间片耗尽)。默认情况下,单个线程能连续执行更多字节码,你的test函数很可能在一个线程的时间片内就跑完整个循环,或者很少被打断,竞态条件几乎不会发生,因此最终i能达到预期的BASE*10。

通用解决方法

不管系统差异,要保证多线程下计数正确,必须用同步机制保护临界区:

  • 使用threading.Lock手动加锁:
import threading

BASE = 1000000

i = 0
lock = threading.Lock()

def test():
    global i
    for x in range(BASE):
        with lock:
            i += 1

threads = [threading.Thread(target=test) for t in range(10)]
for t in threads:
    t.start()

for t in threads:
    t.join()

assert i == BASE*10, (BASE*10, i)
  • 或者使用原子变量(如multiprocessing.Value),避免手动管理锁逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 07:28:19