这是起源问题,但是我的问题有所不同。 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--;
上面的转换并不违反顺序正确性,所以它是正确的,这不是编译器的错,对吗?因此,我同意CODE-1包含数据竞争的观点,那你呢?
我还有一个问题,带有内存模型的C++ 11可以解决此数据争用,因为编译器知道线程,因此它们将根据内存模型类型进行重新排序,对吗?
最佳答案
C++标准将数据争用(触发未定义的行为)定义为:
根据C++内存模型规则,您的第一个代码片段不包含任何数据争用,因为C++标准禁止编译器转换会引入这种争用:
因此,它说,如果if语句(x
)中的条件产生false,则即使最终结果是y
看起来未修改,也不允许进行会修改y
的转换。
第二个示例显然包含一个数据争用,因为2个线程可以同时写入和读取x
(同样适用于y
)。
请注意,自版本11起,C++和C都具有内存模型。如果使用不支持C11的编译器,则不会正式定义多线程行为。
这是question,显示了非法编译器转换的示例。