Gam*_*dot 5 c multithreading memory-model java-memory-model c++11
这是最初的问题,但我的问题与它有一些不同。C++ 内存模型 - 此示例是否包含数据争用?
我的问题:
//CODE-1: initially, x == 0 and y == 0
if (x) y++; // pthread 1
if (y) x++; // pthread 2
Run Code Online (Sandbox Code Playgroud)
注意:上面的代码是用 C 编写的,而不是 C++(没有内存模型)。那么它是否包含数据竞争?
从我的角度来看:如果我们在顺序一致性内存模型中查看代码,则不存在数据竞争,因为 x 和 y 永远不会同时为非零。但是,我们永远不能假设顺序一致性内存模型,因此编译器重新排序可以进行尊重线程内正确性的转换,因为编译器不知道线程的存在......对吗?
所以代码可以改写为:
//CODE-2
y++; if (!x) y--;
x++; if (!y) x--;
Run Code Online (Sandbox Code Playgroud)
上面的转换没有违反顺序正确性,所以它是正确的。这不是编译器的错,对吧?所以我同意 CODE-1 包含数据竞争的观点。你呢?
我有一个额外的问题,带有内存模型的 C++11 可以解决这个数据竞争,因为编译器知道线程,所以他们会根据内存模型类型进行重新排序,对吧?
C++ 标准将数据竞争(触发未定义的行为)定义为:
\n\n\n\n\n\xc2\xa7 1.10.1-2 [intro.races]
\n
\n 如果两个表达式求值之一修改内存位置 (..),而另一个表达式求值读取或修改同一内存位置,则两个表达式求值会发生冲突。
根据 C++ 内存模型规则,您的第一个代码片段不包含数据竞争,因为 C++ 标准禁止会引入此类竞争的编译器转换:
\n\n\n\n\n\xc2\xa7 1.10.1-21 [intro.races]
\n
\n 本国际标准通常排除将分配引入到抽象机不会修改的潜在共享内存位置的编译器转换,因为此类分配可能会覆盖在抽象机执行不会遇到数据竞争的情况下,由不同线程进行另一次分配。
因此,它表示如果 if 语句 ( x) 中的条件产生 false,则不允许进行任何会修改 的转换y,即使最终结果看起来y未修改。
第二个示例显然包含数据竞争,因为 2 个线程可以x同时写入和读取(同样适用于y)。
请注意,C++ 和 C 从版本 11 开始都有内存模型。如果您使用不支持 C11 的编译器,则多线程行为未得到正式定义。
\n\n这是一个显示非法编译器转换示例的问题。
\n