假设x是共享的线程间变量并且func总是返回0,那么下面的代码是否包含C11和C ++ 11的数据竞争?请假设x是用两个不同的线程写的,除了下面的switch语句外,总是有一个正确的锁。
int x; // global variable
...
int y; // local variable
...
switch (func())
{
case 1:
{
x = 0;
y = 1;
break;
}
case 2:
{
x = 0;
y = 2;
break;
}
case 3:
default:
{
y = 3;
break;
}
}
标准中有一个注释(C11和C ++ 11),它排除了编译器转换,从而引入了代码的数据竞争。是否允许编译器转换代码如下所示?下面的代码肯定包含一个数据竞争,但问题是编译器是否已经引入它或者它是否已经在原始代码中。虽然无法访问,但是对共享变量进行了不受保护的访问。
int x; // global variable
...
int y; // local variable
...
temp = x;
x = 0;
switch (func())
{
case 1:
{
y = 1;
break;
}
case 2:
{
y = 2;
break;
}
case 3:
default:
{
x = temp;
y = 3;
break;
}
}
答案 0 :(得分:4)
在C ++标准中,定义了一个种族:
1.10 / 4:如果其中一个修改内存位置而另一个访问或 修改相同的内存位置。
1.10 / 21:如果一个程序的执行在不同的线程中包含两个冲突的动作,则至少有一个 这不是原子的,也不会发生在另一个之前。任何这样的 数据竞争导致未定义的行为。
假设您有多个线程运行相同的代码,由于func()
将始终返回0(您的声明),所以没有任何线程可以更改x的内容。此外,y是由线程执行的函数的局部变量,因此不共享。因此,在这种情况下不会发生竞争条件。
不允许编译器进行与第二个片段相对应的转换,因为:
1.10 / 22:编译器转换,它将分配引入可能不会被修改的共享内存位置 抽象机器通常被这个标准排除在外 赋值可能会覆盖另一个线程的另一个赋值 在抽象机器执行不具备的情况下 遇到了数据竞赛。
但是如果你自己编写片段,在上面解释的条件下可能会遇到竞争条件,因为x不是原子的,并且可能在一个线程(temp=x
)中具有读访问权限而在另一个线程中具有写访问权(或者x=0
或其他帖子的默认部分(x=temp
)