在BSD提供的原子操作中(如原子(9)手册页中所述),有atomic_load_acq_int()
和atomic_store_rel_int()
。在查找其他操作系统的等效项时(例如,通过阅读Mac OS X的原子(3)手册页,Solaris的 atomic_ops (3C)手册页,和Windows的Interlocked*()
函数一样,似乎没有任何(明显的)等价物只是原子地读/写int
。
这是因为默认情况下保证那些对int
进行读/写操作的操作系统是原子的吗? (或者你必须在C / C ++中使用声明它们volatile
吗?)
如果没有,那么如何在这些操作系统上对int
进行原子读/写操作?
(可以通过返回原子加0的结果来模拟原子读取,但是没有等效的原子写入。)
答案 0 :(得分:4)
我认为您正在将atomic memory access与cache coherence混合在一起。前者是在软件(自旋锁,信号量和互斥锁)中构建同步原语所需的硬件支持,而后者是在同一总线上工作的多个芯片(多个CPU和外围设备)的硬件支持,并具有主记忆的一致观点。
不同的编译器/库为第一个提供不同的实用程序。例如,GCC intrinsics for atomic memory access。它们都归结为生成基于compare-and-swap或load-linked/store-conditional的指令块,具体取决于平台支持。编译源代码,例如,-S
用于GCC,并查看生成的汇编程序。
您不必为缓存一致性明确做任何事情 - 它都是在硬件中处理 - 但它肯定有助于理解它如何工作以避免像cache line ping-pong这样的事情。
尽管如此, aligned 单词在所有商品平台上读取和写入都是原子(如果我有人纠正我这里错了。由于int
s的大小小于或等于处理器字,因此您将被覆盖(请参阅上面的GCC内置链接)。
读取和写入的顺序非常重要。这是架构内存模型很重要的地方。它规定了硬件可以和不能重新排序的操作。示例将更新链接列表 - 您不希望其他CPU在项目本身处于一致状态之前看到链接的新项目。可能需要显式memory barriers(通常也称为“内存栅栏”)。 获取屏障确保后续操作不会在屏障之前重新执行(例如,您在项目内容之前读取链接列表项指针),发布屏障确保屏障之后不会重新排序先前的操作(在编写新的链接指针之前编写项目内容)。
volatile
经常被误解为与上述所有相关。实际上,它只是指令编译器不要在寄存器中缓存变量值,而是在每次访问时从内存中读取它。许多人认为并发编程是"almost useless"。
为冗长的回复道歉。希望这有点清楚。
即将推出的C ++ 0x标准最终解决了并发问题,有关详细信息,请参阅Hans Boehm's C++ memory model papers。