1

以下摘录摘自网站https://lwn.net/Articles/262464/,它处理共享数据结构的读取不一致(为此创建了 RCU):

p = gp;
if (p != NULL) {
  do_something_with(p->a, p->b, p->c);
}

尽管此代码片段似乎很可能不会出现错误排序,但不幸的是,DEC Alpha CPU [PDF] 和值推测编译器优化可能会导致 p->a、p->b 和 p- >c 在 p 的值之前被获取!这在值推测编译器优化的情况下可能最容易看到,其中编译器猜测 p 的值,获取 p->a、p->b 和 p->c,然后获取 p 的实际值为了检查它的猜测是否正确。这种优化非常激进,也许是疯狂的,但确实发生在配置文件驱动优化的上下文中。

我不清楚上面的代码是否意味着在访问p->a等时产生错误的 (*) 值,这让我感到害怕,或者它是否意味着“其他 CPU 可以观察到书面(源)顺序”这对我来说完全没问题。

如果第一个解释是正确的,我认为允许这种行为被破坏的系统(编译器)。我的问题是这个东西是否仍然存在,即使流行的架构(Alpha)可能已经消失了。

(*)p->a来自一个记录和p->b另一个记录或更糟的东西的错误值

PS:我没有检查,但我假设gp变量被正确装饰atomic或类似。

4

1 回答 1

1

C++

那篇文章写于 2007 年,所以它早于 C++11。

C++11 是第一个在标准中定义任何关于线程的东西,并用它定义了1什么构成或不构成数据竞争。

根据现行规则,我相信您的结论基本上是正确的——引用的代码、评估p->ap->b/或p->c何时p==NULL会违反标准的要求,除非在 as-if 规则下(即,如果系统可以确保评估它们没有明显的效果,即使p是空指针)。

C

这里的故事几乎相同——C11 标准是第一个定义线程以及在使用它们时如何进行排序的标准。因此,在撰写文章时,该标准没有任何规则。尽管他们不使用相同的术语,但 C 和 C++ 委员会已经对此进行了协调,因此我相信他们至少打算在这方面使两种语言的规则相同。


1. 好吧,无论如何,它都在尝试——如果没记错的话,在 2011 年标准中的定义方式中发现了一些漏洞,因此在较新的标准中进行了更新。但重点是,在2011年标准之前,它甚至没有尝试过。
于 2021-02-12T17:51:09.883 回答