将相同的值重新写入内存位置是否算作修改内存? (在多线程的情况下)

问题描述 投票:0回答:2

(假设:

int x{ 6 }
和2个评价同时写
x = 6

--

CPP 参考文献介绍了多线程执行和数据竞争 |数据竞赛:

表达式的计算写入到内存位置并且 另一个评估读取修改相同的内存位置, 据说表达式是冲突的。一个程序有两个冲突 评估存在数据竞争,除非:

  • 两个评估都在同一线程或同一信号中执行 处理程序,或

  • 两个相互冲突的评估都是原子操作(参见 std::atomic),或

  • 其中一个相互矛盾的评估发生在 另一个(参见 std::memory_order)。

如果发生数据竞争,程序的行为是不确定的。

参考文献说:“另一个评估修改;它没有说“另一个评价

--

C++ 标准关于 6.9.2.2 数据竞争的规定

  1. 两个表达式求值冲突,如果 其中一个 修改 内存位置 ([intro.memory]) 且 另一个 读取 修改相同的内存位置。

--

将相同的值重新写入内存位置是否算作修改内存?

c++ multithreading c++11 memory-model data-race
2个回答
5
投票

向内存位置写入相同的值算作修改内存吗?

是的,例如,对标量对象的简单赋值(这就是内存位置实际上是什么,位字段除外)被定义为修改对象,无论对象要更改为什么值。请参阅 [expr.ass]/2:

  1. 在简单赋值 (=) 中,左操作数引用的对象通过将其值替换为右操作数的结果而被修改 ([defns.access])。

您会发现影响标量对象值的所有其他表达式都有类似的措辞。


关于术语,标准通常不使用“write”,而是使用“modify”,含义相同。参见例如[defns.access].


3
投票

简短的回答是,修改意味着发生对对象的任何写访问。 即使这不会改变内存中的任何位,它也会修改抽象 C++ 意义上的值。

通过在抽象 C++ 意义上修改内存,您可能会遇到数据竞争,即使此修改不会更改内存中的任何位。

长答案

要获得更清晰的了解,请参阅 C++11 标准,[intro.multithread] p21:

注意:我引用 C++11 因为这是一个 问题。

如果程序在不同线程中包含两个冲突的操作,则该程序的执行包含“数据争用”,并且至少其中一个不是原子的,并且两者都不会在另一个之前发生。任何此类数据竞争都会导致未定义的行为。

相关的写法是
conflict

,定义于[intro.multithread] p4:

如果两个表达式求值之一修改 ([intro.memory]) 内存位置,而另一个表达式求值访问或修改同一内存位置,则两个表达式求值会发生冲突。

不幸的是,这就是事情变得不清楚的地方,因为“修改”实际上并没有在标准中定义;它没有在
[intro.defs]

中定义。 最合理的解释

编辑 3470

在许多地方澄清了访问的含义。 access 表示读取或修改值。 冲突的当前定义也使用这种“读取或修改”术语,在[intro.races](工作草案)中。 标准中使用“访问”和“读取或修改”的方式通常不需要在修改之前/之后比较不相等的值。

如果通过错误的类型修改某些内容,即使内存中没有任何位发生更改,也违反了严格别名,并且
  • 按照相同的逻辑,即使不更改内存中的任何位,也可以修改值,并且可能会遇到数据争用。
  • 关于价值观和修改的进一步思考

另请注意,在工作草案中(尽管不在 C++11 中),分配始终会根据

[expr.ass] p2 (工作草案)修改值

:

在简单赋值 (
=

) 中,通过用右操作数的结果替换其值来修改左操作数引用的对象 ([defns.access])。


不要求新值与旧值比较不相等。对象总是会被修改。

您可以更改位,而不会发生任何可观察到的值变化

0 == 0; // guaranteed true, because zero compares equal to zero int x = 0; x = 0; // if int is padded, then this might modify padding bits of int // even though the values compare equal before and after, bits are changed

您可以更改值而不更改任何存储位

另请注意,

value

通常指对象的状态。两个值是不同的,即使它们比较相等: int x; // x has no value, but all of the bits in the storage could be zero here std::construct_at(&x); // x now has value zero, and while this does change its value // (it was indeterminate before), it might not have any affect // on the bits of its storage

如您所见,更改内存中的位与修改值是不同的概念。
赋值
总是

改变值。

© www.soinside.com 2019 - 2024. All rights reserved.