假设我们有下面的代码
int test(bool* flag, int* y)
{
if(*y)
{
*flag = false;
else
{
*flag = true;
}
}
注意,编译器可以在这里证明write to flag总是会发生,所以我认为下面的一个是允许的(我不认为它是优化的,但只是为了示例)
int test(bool* flag, int* y)
{
*flag = true;
if(*y)
{
*flag = false;
}
}
所以现在,我们也将true写入flag if y!=0
,但是从as-if规则来看,这看起来是有效的。
但我仍然认为,这种优化是奇怪的,假设*y = true
总是,所以标志总是假的,所以如果其他一些线程读取标志变量,他可能会看到真的,虽然它不应该发生,所以它打破了as-if规则?优化是否有效?
补充:非原子的情况是清楚的,因为它的UB,所有的赌注都是关闭的,但如果标志是原子的,放松排序,然后呢?
2条答案
按热度按时间3pmvbmvn1#
转换是有效的(仅基于标准定义的内容,即:即假设严格的混叠)。
任何其他线程都不可能观察到中间值,因为当函数在另一个线程上执行时,不允许任何线程读取
*flag
。*flag
不是一个原子对象,该函数总是写入*flag
,而另一个线程阅读它时不同步,因此会导致未定义的行为,因为它是一个数据竞争,而不管采取的路径如何。如果
flag
的类型是(std::)atomic_bool*
,那么,不管使用什么内存顺序,转换通常都是无效的,因为,正如你所说的,另一个线程可能会观察到一个它本不应该观察到的值。ivqmmu1c2#
给出:
以下(与OP的代码略有不同)是不允许的
...因为指向同一类型数据的指针可能指向同一条数据:即指针相同。那么代码更改在功能上就不一样了。
如果代码为:
然后编译器可以假设指针不指向重叠的数据,即使它们指向相同的类型。