这段C++自增函数代码是否线程安全?若不安全该如何修改?
代码线程安全性评估与修改方案
线程安全性判断
这段代码不是线程安全的。
原因在于cnt = cnt + 1这个自增操作并非原子操作,它会被编译器拆解为三个独立的步骤:
- 从内存中读取
cnt的当前值到寄存器 - 在寄存器中对该值执行加1操作
- 将计算结果写回内存中的
cnt
当多个线程同时执行incr_fun时,可能出现线程A读取cnt后,线程B也读取了同一个值,两者各自加1后写回,最终cnt只增加了1而非2,这种竞态条件会导致计数结果不准确。
修改方案
方案1:使用互斥锁(std::mutex)
通过互斥锁保护临界区,确保同一时间只有一个线程能执行自增操作:
#include <iostream> #include <thread> #include <mutex> using namespace std; static int cnt = 0; static mutex cnt_mutex; // 定义互斥锁 void incr_fun() { lock_guard<mutex> lock(cnt_mutex); // 自动管理锁的生命周期,避免忘记解锁 cnt = cnt + 1; }
方案2:使用原子变量(std::atomic)
C++标准库提供的std::atomic类型支持原子操作,无需额外锁即可保证线程安全:
#include <iostream> #include <thread> #include <atomic> using namespace std; static atomic<int> cnt = 0; // 声明为原子变量 void incr_fun() { cnt.fetch_add(1); // 原子自增操作,等价于 cnt++ // 或者直接使用 cnt++,atomic<int>重载了operator++ }
两种方案对比:
- 互斥锁适合保护多个操作组成的临界区,灵活性高,但有一定的锁开销。
- 原子变量针对单个变量的原子操作,性能通常比互斥锁更好,代码更简洁。
内容的提问来源于stack exchange,提问作者Johann
相关产品推荐
相关产品推荐

