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

已使用std::mutex保护访问时,是否仍需使用std::atomic?

问题解答

代码是否存在未定义行为?

这段代码没有未定义行为。核心原因是所有对sm_foo的读写操作都被同一个std::mutex完全保护:

  • 每次调用GetFoo()都会先获取锁,确保同一时间只有一个线程能进入临界区。
  • sm_foo的初始化(内存分配、成员变量赋值)全程在锁的保护下完成,其他线程只有在初始化彻底完成后,才能通过锁的同步看到完整的Foo对象。

注意:代码里存在一个语法错误——全局变量定义Foo* sm_foo = nullptr;应该改为Foo* Foo::sm_foo = nullptr;,否则会定义一个全局的sm_foo而非类的静态成员,但这属于语法问题,并非多线程相关的未定义行为。

使用std::mutex是否符合C++内存模型?

完全符合。C++内存模型明确规定,std::mutex的加锁(lock())和解锁(unlock())操作自带内存屏障语义:

  • 解锁操作会强制将临界区内的所有内存写操作同步到主存,确保后续获取同一锁的线程能看到这些修改。
  • 加锁操作会同步线程的内存状态,保证线程读取到的是最新的主存数据。
    简单来说,锁的存在让临界区内的操作等价于按顺序执行,不会出现指令重排导致的对象未完全初始化就被读取的问题。

弱内存序平台上的表现

在ARM、PowerPC这类弱内存序平台上,这段代码依然能正常运行,不会出现问题。因为std::mutex的同步语义是C++标准强制要求的,与平台底层内存序无关:

  • 锁的底层实现会针对对应平台插入必要的内存屏障指令,确保临界区内的写操作不会被重排到解锁之后,读操作不会被重排到加锁之前。
  • 对比无锁的双重检查锁定模式(那种场景下弱内存序会导致对象未完全初始化就被读取),这段代码全程用锁保护,不存在此类风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:12:35