原子操作在进程间的工作方式是不是与它们在线程间的工作方式相同?
Posted
技术标签:
【中文标题】原子操作在进程间的工作方式是不是与它们在线程间的工作方式相同?【英文标题】:Do atomic operations work the same across processes as they do across threads?原子操作在进程间的工作方式是否与它们在线程间的工作方式相同? 【发布时间】:2009-10-18 17:43:54 【问题描述】:显然,原子操作确保不同的线程不会破坏一个值。但是,当使用共享内存时,跨进程是否仍然如此?即使这些进程碰巧被操作系统安排在不同的内核上运行?还是跨不同的不同 CPU?
编辑:另外,如果它不安全,即使在像 Linux 这样的操作系统上,从调度程序的角度来看,进程和线程是相同的,它是否也不安全?
【问题讨论】:
【参考方案1】:tl;dr: 阅读原子操作文档中的细则。有些设计是原子的,但可能会跳过某些变量类型。不过,一般来说,原子操作将在不同进程之间保持其契约,就像在线程之间一样。
原子操作实际上只能确保在被两个实体同时调用时不会出现不一致的状态。例如,由两个不同线程或进程在同一个整数上调用的原子增量将始终表现如下:
-
x = 初始值(本次讨论为零)
实体 A 递增 x 并将结果返回给自身:result = x = 1。
实体 B 增加 x 并将结果返回给自身:result = x = 2。
其中 A 和 B 表示进行调用的第一个和第二个线程或进程。
由于竞态条件、对地址空间的不完整写入等原因,非原子操作可能会导致不一致或通常很疯狂的结果。例如,您可以很容易地看到:
-
x = 初始值 = 再次为零。
实体 A 调用 x = x + 1。要计算 x + 1,A 检查 x 的值(零)并加 1。
实体 B 调用 x = x + 1。要计算 x + 1,B 检查 x 的值(仍为零)并加 1。
实体 B(幸运)首先完成并将 x + 1 = 1(步骤 3)的结果分配给 x。 x 现在是 1。
实体 A 获得第二名,并将 x + 1 = 1(步骤 2)的结果分配给 x。 x 现在是 1。
注意竞争条件,因为实体 B 超越 A 并首先完成表达式。
现在想象一下,如果 x 是一个 64 位双精度数,则不能保证具有原子分配。在这种情况下,您很容易看到如下内容:
-
64 位双精度 x = 0。
实体 A 尝试将 0x1122334455667788 分配给 x。首先分配前 32 位,将 x 保留为 0x1122334400000000。
实体 B 竞相进入并将 0xffeeddccbbaa9988 分配给 x。偶然地,两个 32 位的一半都更新了,现在 x = 0xffeeddccbbaa9988。
实体 A 完成后半部分的分配,现在 x = 0xffeeddcc55667788。
这些非原子分配是您必须诊断的一些最可怕的并发错误。
【讨论】:
以上是关于原子操作在进程间的工作方式是不是与它们在线程间的工作方式相同?的主要内容,如果未能解决你的问题,请参考以下文章