【发布时间】:2014-10-02 18:18:17
【问题描述】:
从 x = 0 开始。请注意,以下任何代码中都没有内存屏障。
易失性 int x = 0
线程 1:
while (x == 0) {}
print "Saw non-zer0"
while (x != 0) {}
print "Saw zero again!"
线程 2:
x = 1
是否有可能在任何(真实的)CPU 上看到第二条消息“又看到零了!”?在 x86_64 上呢?
同样,在这段代码中:
易失性 int x = 0。
线程 1:
while (x == 0) {}
x = 2
线程 2:
x = 1
x 的最终值是否保证为 2,或者 CPU 缓存是否可以以任意顺序更新主内存,这样虽然 x = 1 进入 CPU 的缓存,线程 1 可以看到它,但线程 1 被移动到另一个 cpu,它将 x = 2 写入该 cpu 的缓存,并且 x = 2 在 x = 1 之前被写回主内存。
【问题讨论】:
-
在 C 语言的上下文中说:由于这是一场数据竞争,而数据竞争是未定义的行为,那么任何事情都可能发生。试图推理它真的没有多大意义。
-
没有编程语言就无法回答(无论是 x86 指令)。
-
在大多数语言中,编译器可以合法地将
print(x); print(x);重写为old = x; print(x); print(old);。所以大多数语言的答案是肯定的。 -
@MichaelBurr 在 C 语言的上下文中,共享对象上只有
volatile操作,根据 ABI,这些操作必须准确执行;这是可观察行为的一部分。因此,当读取和写入符合 ABI(相应对齐)的int对象时,我们完全拥有 CPU 提供的语义。没有 UB,只有 ABI 和 CPU 特定的行为。 -
@usr 在 C 和 C++ 中,volatile 的意思是:在 asm 中按照确切的顺序执行这些内存操作。并且不要优化任何此类操作,即使它可能看起来是多余的。
标签: multithreading consistency cpu-cache