是在x86-64多核计算机上读取和写入C++原子中的int

2022-04-18 00:00:00 multithreading atomic c++ cpu-cache

我已阅读this,我的问题非常相似,但略有不同。

注意,我知道C++0x不能保证这一点,但我特别要求像x86-64这样的多核计算机。

假设我们有两个线程(固定到两个物理核心)运行以下代码:

// I know people may delcare volatile useless, but here I do NOT care memory reordering nor synchronization/
// I just want to suppress complier optimization of using register.
volatile int n; 

void thread1() {
    for (;;)
        n = 0xABCD1234;
        // NOTE, I know ++n is not atomic,
        // but I do NOT care here.
        // what I cares is whether n can be 0x00001234, i.e. in the middle of the update from core-1's cache lines to main memory,
        // will core-2 see an incomplete value(like the first 2 bytes lost)?
        ++n; 
    }
}

void thread2() {
    while (true) {
        printf('%d', n);
    }
}

线程2是否有可能看到n类似于0x00001234,即在从core-1的缓存线更新到主存的过程中,core-2是否会看到不完整的值?

我知道单个4字节绝对适合一个典型的128字节长的缓存线,如果确实存储在一个缓存线中,那么我相信这里不会有问题...然而,如果它越过高速缓存线边界怎么办?即,是否有可能一些char已经位于使n的第一部分在一个高速缓存线中而另一部分在下一线中的高速缓存线内?如果是这样,那么CORE-2可能有机会看到不完整的值,对吗?

另外,我认为除非将每个charshort或其他less-than-4-bytes类型填充为4字节长,否则永远无法保证单个int不会通过高速缓存线边界,不是吗?

如果是这样,是否建议即使设置单个int也不能保证在x86-64多核计算机上是原子计算机?

我提出这个问题是因为当我研究这个主题时,不同职位的人似乎都同意,只要机器体系结构正确(例如x86-64),int设置应该是原子的。但正如我上面所说的,这是站不住脚的,对吗?

更新

我想介绍一下我的问题的背景。我处理的是一个实时系统,它对一些信号进行采样,并将结果放入一个全局int中,这当然是在一个线程中完成的。在另一个线程中,我读取了这个值并对其进行处理。 我不关心set和get的顺序,我所需要的只是一个完整的(与损坏的整数值)值。


解决方案

另一个问题谈到变量"正确对齐"。如果它跨越缓存线,则变量未正确对齐。例如,除非您明确要求编译器打包一个结构,否则int不会这样做。

您还假设使用volatile int比使用atomic<int>更好。如果volatile int是在您的平台上同步变量的完美方式,那么库实现人员肯定也会知道这一点,并在atomic<x>中存储一个volatile x

并不要求atomic<int>必须特别慢,因为它是标准的。:-)

相关文章