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

多线程访问全局变量:是否需要使用互斥锁?

多线程读写全局变量是否需要互斥锁?

嘿,这个问题问到点子上了——咱们直接给结论:在这个场景下,不加互斥锁绝对是不安全的,而且必须要引入同步机制,我来拆解清楚背后的原因:

核心问题1:变量的可见性

就算g_flag是32位整数(看起来读写好像是“一次性完成”的),编译器和CPU的优化会给你挖大坑:

  • 编译器可能会把getFlag()里的读取操作优化成只从CPU缓存/寄存器里取旧值,不会每次都去主内存读取最新的g_flag。也就是说,线程thd1修改了g_flag之后,thd2可能永远看不到这个更新,一直读到旧值。
  • 互斥锁的作用不只是“互斥”,更关键的是它会触发内存屏障:当thd1解锁io_mutex时,会把修改后的g_flag强制刷新到主内存;当thd2加锁时,会强制从主内存重新读取g_flag,保证拿到的是最新值。

核心问题2:原子性的误区

很多人觉得“32位整数的读写是原子的,所以没问题”,但这是个错误的认知:

  • C++标准并没有保证普通std::int32_t的读写是原子操作,只有std::atomic系列类型的操作才是标准明确规定的原子操作。
  • 就算在大多数现代CPU上32位读写是原子的,没有内存屏障的话,还是会出现上面说的可见性问题——线程之间的修改无法同步。

更好的替代方案?

如果只是单纯的读写一个整数,其实用std::atomic<std::int32_t>会比互斥锁更轻量:

static std::atomic<std::int32_t> g_flag;

void setFlag(std::int32_t flag) {
    g_flag = flag;
}

std::int32_t getFlag() {
    return g_flag;
}

原子类型本身就提供了可见性和原子性保证,不需要互斥锁就能安全地在多线程间读写。

总结

  • 不管是用互斥锁还是原子类型,必须加同步机制,否则会出现变量不可见、甚至在某些特殊平台上的原子性问题。
  • 不要依赖硬件的“默认原子性”,要严格遵循C++标准的同步规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:10:54