2017-02-11 109 views

回答

9

由于xy均为零,由C++标准中定义的抽象机不能写入任一存储器的位置,所以这可能是一个问题的唯一方法是,如果执行决定写入到存储器位置反正。例如,如果它转化

if (x) y = 1; 

y = 1; 
if (!x) y = 0; 

这是根据作为-如果因为任何一个线程的观察到的行为的规则是相同的(C++ 14 1.9潜在有效重写[intro.execution])

该国际标准中的语义描述定义了一个参数化的非确定性抽象 机器。本国际标准没有要求符合实施的结构。 特别是,他们不需要复制或模拟抽象机器的结构。相反,需要遵守 实现来模拟(仅)抽象机器的可观察行为,如下面解释的 。

这实际上在C++ 11之前是有效的重写,但是自从C++ 11开始考虑执行线程之后。因此,只要没有数据竞争发生在抽象机器中,就不允许实现进行更改,以便跨线程观察到不同的行为。

在C++ 14标准中有一个特别注释,它适用于此(C++ 14 1.10 [into。多线程]段落22)

[注:编译器变换该引进分配到一个潜在的共享存储器位置的是 不会被抽象机被修改通常由该标准排除,因为这种 分配可能会覆盖另一在执行抽象机器时不会遇到数据竞争的情况下由不同线程分配。 ...

因此,重写无效。该实现必须保留所观察到的行为,即使在线程间也不会修改xy。因此,没有数据竞赛。

13

这两个线程都不会写入,因为这两个变量在条件之前都不为零。

11

数据竞赛不是您的代码的静态属性。它们是执行时程序实际状态的属性。所以虽然该程序可能是处于代码会产生数据竞争的状态,但这不是问题。

问题是,考虑到系统的状态,代码是否会导致数据竞争?由于程序处于这样一种状态,即任何线程都不会写入任何变量,因此代码不会导致数据竞争。

数据竞赛不是你的代码可能做的。这是关于他们会做什么。就像一个接受指针的函数不是未定义行为一样,因为它使用指针而不检查NULL。如果有人传递了一个真正为NULL的指针,那只有UB。

2

我发现这篇文章由Hans-J撰写。波姆照明:
http://www.hpl.hp.com/techreports/2009/HPL-2009-259html.html#races

我们说两个普通存储器操作冲突,如果他们访问 同一存储器位置(例如,可变或数组元素),和在他们的 至少一个写入地点

我们说一个程序允许在一组特定的输入 数据竞争,如果有一个顺序一致的执行,即各个线程的操作的 交织,其中两个 发生冲突操作可以同时“执行”。对于我们的 目的,如果 它们在交错中彼此紧挨着并且对应于不同的线程,则可以“同时”执行两个这样的操作。

而且文章接着我们的观点:

我们的数据竞争的定义是相当严格的:必须有执行原来的,未转换的程序的 实际的方式,使得 冲突操作并行发生。这给编译器带来了负担,不会通过引入有害的数据竞争来“破坏”程序。

正如文章,报告了同样的例子(及其他)中所述: 有这个程序没有顺序一致的执行中,线程1个受让人为y因为x和y不会成为非零 。事实上,你永远不会满足条件,所以没有人写信给另一个线程可能正在阅读的变量。

要了解与将数据种族存在的情况下的差异,试着想想文章下面的例子:

y = ((x != 0)? 1 : y) # Thread 1 
y = 2;     # Thread 2 

在很显然最后这种情况下,可以发生Y是分配(写)由线程1执行,而线程2执行时y = 2;y由线程1写入,无论如何)。数据竞赛可能发生。

0

如果未设置x,则不会将y设置为1,反之亦然。所以,这里的事情确实是顺序发生的。

相关问题