VS2017 64位项目中多核CPU上32位变量读取的原子性疑问
多核CPU环境下32位变量直接读取的原子性问题
首先直接给结论:在你的VS2017 64位项目中,对齐的32位LONG类型变量m_lClosed的直接读取操作是具备原子性的。下面展开说细节:
- 硬件层面的保证:x86/x64架构的CPU对自然对齐的32位数据的单次load(读取)操作是原子的——也就是说,线程2读取
m_lClosed时,不会读到一个“半更新”的值(比如线程1正在把0改成1,不会读到中间的部分字节),哪怕是在多核环境下。这是CPU架构本身提供的特性。 - 编译器层面的支持:VS2017在处理这种简单的直接读取(比如
if (m_lClosed...))时,会生成单次的内存读取指令,不会把读取拆分成多个字节操作,所以不会破坏原子性。
不过这里要提醒一个容易混淆的点:原子性≠可见性。哪怕读取是原子的,线程2可能还是会读到缓存里的旧值,因为多核CPU的缓存一致性需要显式的内存语义来保证。如果你需要线程2能立刻看到线程1用InterlockedCompareExchange修改后的最新值,那直接读取可能不够——这时候你可以:
- 把变量声明为
volatile LONG m_lClosed(VS里对volatile的处理会保证可见性,但注意标准C++里它的内存语义更弱); - 用
Interlocked系列的读取函数,比如InterlockedExchangeAdd(&m_lClosed, 0)来读取当前值,这类函数自带内存屏障,能保证可见性; - 改用C++标准库的
std::atomic<int32_t>,它能同时保证原子性和可控的内存语义,是更规范的做法。
另外补充:如果变量是未对齐的,那读取可能就不是原子的,但VS2017默认会对基本类型做自然对齐(32位LONG会按4字节对齐),所以你的场景里不用担心这个问题。
内容的提问来源于stack exchange,提问作者Wad
相关产品推荐
相关产品推荐

