3

在 BSD 提供的原子操作中(如atomic (9) 手册页所示),有atomic_load_acq_int()atomic_store_rel_int()。在寻找其他操作系统的等价物时(例如,通过阅读Mac OS X 的 atomic (3) 手册页、Solaris 的atomic_ops ( 3C) 手册页以及Interlocked*()Windows 的函数),似乎没有仅以原子方式读取/写入int.

这是因为int默认情况下保证读/写的那些操作系统是原子的吗?(或者您必须volatile在 C/C++ 中声明它们吗?)

如果不是,那么如何int在这些操作系统上进行原子读/写?

(可以通过返回 0 的原子加法的结果来模拟原子读取,但没有等效的原子写入。)

4

1 回答 1

4

我认为您将atomic memory accesscache coherence混合在一起。前者是在软件中构建同步原语(自旋锁、信号量和互斥锁)所需的硬件支持,而后者是对在同一总线上工作的多个芯片(多个 CPU 和外围设备)的硬件支持,并且具有主存储器的一致视图。

不同的编译器/库为第一个提供不同的实用程序。例如,这里是原子内存访问的 GCC 内在函数。它们都归结为根据平台支持生成比较和交换或基于加载链接/存储条件的指令块。例如,-S使用 GCC 编译您的源代码并查看生成的汇编程序。

您不必明确地为缓存一致性做任何事情——这一切都在硬件中处理——但它肯定有助于理解它是如何工作的,以避免像缓存行 ping-pong这样的事情。

尽管如此,对齐的单个单词读写在所有商品平台上都是原子的(如果我在这里错了,请有人纠正我)。由于ints 在大小上小于或等于处理器字,因此您已被覆盖(请参阅上面的 GCC 内置链接)。

重要的是读取和写入的顺序。这就是架构内存模型很重要的地方。它规定了哪些操作可以和不能由硬件重新排序。示例是更新链接列表 - 在项目本身处于一致状态之前,您不希望其他 CPU 看到链接的新项目。可能需要显式内存屏障(通常也称为“内存栅栏”)。获取屏障确保后续操作不会在屏障之前重新排序(例如,您在项目内容之前读取链表项指针),释放屏障确保之前的操作不会在屏障之后重新排序(您编写写入新链接指针之前的项目内容)。

volatile经常被误解为与上述所有内容有关。实际上,它只是对编译器的一条指令,不要在寄存器中缓存变量值,而是在每次访问时从内存中读取它。许多人认为它对于并发编程“几乎没用” 。

抱歉冗长的回复。希望这可以清除它。

编辑:

即将推出的 C++0x 标准最终解决了并发问题,有关许多详细信息,请参阅Hans Boehm 的 C++ 内存模型论文

于 2010-07-11T16:50:46.303 回答