此示例是否包含数据竞争?

Does this example contain a data race?

这里是原题,我的跟原题有些出入。 C++ memory model - does this example contain a data race?

我的问题:

//CODE-1: initially, x == 0 and y == 0
if (x) y++; // pthread 1
if (y) x++; // pthread 2

注意:上面的代码是用C写的,不是C++(没有内存模型)。那么它是否包含数据竞争?

从我的角度来看:如果我们查看顺序一致性内存模型中的代码,则不会出现数据竞争,因为 x 和 y 永远不会同时为非零值。然而,我们永远不能假设一个顺序一致性内存模型,所以编译器重新排序可以进行一个关于线程内正确性的转换,因为编译器不知道线程的存在......对吧?

所以代码可以转换为:

//CODE-2
y++; if (!x) y--;
x++; if (!y) x--;

上面的转换没有违反顺序正确性,所以 correct.It 不是编译器的错,对吧?所以我同意CODE-1包含关于你的数据race.What的观点?

我有一个额外的问题,带有内存模型的 C++11 可以解决这个数据竞争,因为编译器知道线程,所以他们会根据内存模型类型重新排序,对吗?

//CODE-1: initially, x == 0 and y == 0
if (x) y++; // pthread 1
if (y) x++; // pthread 2

没有未定义的行为,因为 x 和 y 都不会改变它们的值。
但是,仍然存在竞争条件,因为在一个线程中的读访问和另一个线程中的写访问之间没有定义的顺序。

//CODE-2
y++; if (!x) y--; // pthread 1
x++; if (!y) x--; // pthread 2

现在您有数据竞争和未定义的行为,因为线程 1 中的 y++ 和线程 2 中的 if(!y) 之间没有序列,反之亦然。所以 y 的可能结果是:

  • y = 0
    线程 1 在线程 2 之后运行。所以 x 仍然是 0。
  • y = 1
    线程 1 与线程 2 并行运行,看到对 x 的更改,但反之则不然。所以y没有递减。

这与内存模型无关。这只是任何非同步上下文中的一场比赛。

C++ 标准将数据竞争(触发未定义行为)定义为:

§ 1.10.1-2 [intro.races]
Two expression evaluations conflict if one of them modifies a memory location (..) and the other one reads or modifies the same memory location.

根据 C++ 内存模型规则,您的第一个代码片段不包含数据竞争,因为 C++ 标准禁止会引入此类竞争的编译器转换:

§ 1.10.1-21 [intro.races]
Compiler transformations that introduce assignments to a potentially shared memory location that would not be modified by the abstract machine are generally precluded by this International Standard, since such an assignment might overwrite another assignment by a different thread in cases in which an abstract machine execution would not have encountered a data race.

所以它说,如果 if 语句 (x) 中的条件为假,则不允许进行会修改 y 的转换,即使最终结果是 [=11] =] 显示为未修改。

第二个示例显然包含数据竞争,因为 2 个线程可以同时写入和读取 x(同样适用于 y)。

请注意,C++ 和 C 从版本 11 开始都有内存模型。如果您使用不支持 C11 的编译器,多线程行为未正式定义。

这里有一个 显示了非法编译器转换的示例。