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

pthreads多线程C代码输出异常原因及概念误区解析

多线程自增全局变量结果异常的原因解析

你的核心误区是把d++当成了原子操作——但实际上这个自增语句在底层会被拆成三个独立的CPU指令:

  • 从内存中读取全局变量d的当前值到寄存器
  • 寄存器中的值加1
  • 将新值写回内存中的d

这三步不是不可分割的,当多个线程同时执行这组指令时,就会出现竞态条件:
比如线程A刚读完d=100,还没来得及加1写回,线程B也读取了d=100;之后A把101写回,B紧接着也把101写回。这相当于两次自增操作,最终d只增加了1,凭空少了一次增量。

你觉得“自增顺序不影响总和”,这个结论只在每个自增操作完整执行后,下一个操作才开始的前提下成立。但多线程环境中,线程的执行是被操作系统调度器随机打断的,指令执行顺序会交错,就会出现上面的覆盖情况,次数多了最终结果自然远小于预期的500000。

解决办法

  • 互斥锁:给自增操作加锁,确保同一时间只有一个线程能执行d++:
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    
    // 线程函数中
    for (int i = 0; i < 100000; i++) {
        pthread_mutex_lock(&mutex);
        d++;
        pthread_mutex_unlock(&mutex);
    }
    
  • 原子类型:使用C11标准的原子变量代替普通全局变量,让自增操作变成原子指令:
    #include <stdatomic.h>
    atomic_int d = ATOMIC_VAR_INIT(0);
    
    // 线程函数中
    for (int i = 0; i < 100000; i++) {
        atomic_fetch_add(&d, 1);
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:17:35