对象初始化是否属于内存位置修改?C++并发冲突动作判定
C++内存模型:对象初始化与数据竞争判定
示例代码
struct A{int a; A():a(1){}} std::atomic<A*> x; // 线程1: A* ptr = new A(); // #1 x.store(ptr,memory_order::relaxed); //线程2: auto ptr = x.load(memory_order::relaxed); int b = ptr->a; // #2
相关C++标准规则
数据竞争的判定逻辑
以下情况的两个动作具有潜在并发性:
- 由不同线程执行,或
- [...]
若程序执行中包含两个潜在并发的冲突动作,且至少其中一个是非原子操作,且两者无先行关系,则存在数据竞争(data race)。
冲突动作的定义
若两个表达式求值中,一个修改内存位置,另一个读取或修改同一内存位置,则两者构成冲突。
问题核心与标准解释
示例中#1(线程1里new A()完成的对象初始化)与#2(线程2读取ptr->a)无先行关系,#1属于非原子操作,但关键疑问是:对象初始化是否属于“修改内存位置”?
结合C++标准的底层定义,可以明确:
- 内存位置的界定:
A::a是int类型的标量对象,属于标准定义的独立内存位置。 - 初始化的本质:
new A()的执行流程是先分配内存,再调用构造函数将a赋值为1。构造函数对a的赋值,就是对该内存位置的写操作——完全符合标准中“修改内存位置”的定义。 - 数据竞争的结论:#1中对
A::a的非原子修改,与#2中对同一内存位置的读取,属于潜在并发的冲突动作,且两者无先行关系(relaxed内存序下,store和load操作不建立同步关系)。因此,该示例存在数据竞争。
内容的提问来源于stack exchange,提问作者xmh0511
相关产品推荐
相关产品推荐

