我认为您将atomic memory access与cache coherence混合在一起。前者是在软件中构建同步原语(自旋锁、信号量和互斥锁)所需的硬件支持,而后者是对在同一总线上工作的多个芯片(多个 CPU 和外围设备)的硬件支持,并且具有主存储器的一致视图。
不同的编译器/库为第一个提供不同的实用程序。例如,这里是原子内存访问的 GCC 内在函数。它们都归结为根据平台支持生成比较和交换或基于加载链接/存储条件的指令块。例如,-S
使用 GCC 编译您的源代码并查看生成的汇编程序。
您不必明确地为缓存一致性做任何事情——这一切都在硬件中处理——但它肯定有助于理解它是如何工作的,以避免像缓存行 ping-pong这样的事情。
尽管如此,对齐的单个单词读写在所有商品平台上都是原子的(如果我在这里错了,请有人纠正我)。由于int
s 在大小上小于或等于处理器字,因此您已被覆盖(请参阅上面的 GCC 内置链接)。
重要的是读取和写入的顺序。这就是架构内存模型很重要的地方。它规定了哪些操作可以和不能由硬件重新排序。示例是更新链接列表 - 在项目本身处于一致状态之前,您不希望其他 CPU 看到链接的新项目。可能需要显式内存屏障(通常也称为“内存栅栏”)。获取屏障确保后续操作不会在屏障之前重新排序(例如,您在项目内容之前读取链表项指针),释放屏障确保之前的操作不会在屏障之后重新排序(您编写写入新链接指针之前的项目内容)。
volatile
经常被误解为与上述所有内容有关。实际上,它只是对编译器的一条指令,不要在寄存器中缓存变量值,而是在每次访问时从内存中读取它。许多人认为它对于并发编程“几乎没用” 。
抱歉冗长的回复。希望这可以清除它。
编辑:
即将推出的 C++0x 标准最终解决了并发问题,有关许多详细信息,请参阅Hans Boehm 的 C++ 内存模型论文。