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
相关产品推荐
相关产品推荐

