基于C++内存模型定义,判断给定代码是否存在数据竞争?
问题分析与解答
核心定义回顾
根据C++内存模型定义:
- 当一个表达式修改某内存位置,另一个表达式读取或修改同一内存位置时,这两个表达式存在冲突。
- 存在冲突表达式的程序,若不满足以下任一条件则存在数据竞争:
- 两个表达式在同一线程或信号处理程序中执行;
- 均为原子操作;
- 其中一个表达式happens-before另一个。
本文仅关注第3条。
给定代码
std::atomic<int> x = 0; int y; int z; std::jthread th1([&]{ y = 1; x.store(1, std::memory_order_release); }); std::jthread th2([&]{ z = (z++, ((x.load(std::memory_order_acquire) == 1)? y : 0)); });
前提假设
假设x.load(std::memory_order_acquire)返回1,此时:
- 线程2中读取
y的操作(即(x.load(...) ==1 ) ? y :0里的y读取)与线程1的y = 1操作因涉及同一变量y存在冲突; z++的求值并不happens-beforey = 1。
是否存在数据竞争?
不存在数据竞争。
关键分析
我们只需要关注存在冲突的那对表达式:线程1的y=1,和线程2中读取y的操作。
根据release-acquire语义:
线程1中x.store(1, std::memory_order_release)是release操作,线程2中x.load(std::memory_order_acquire)是acquire操作且返回了1,这意味着线程1中所有在release操作之前的内存操作(包括y=1)都happens-before线程2中acquire操作之后的所有内存操作(包括读取y的操作)。
这对冲突表达式满足“其中一个happens-before另一个”的条件,因此程序不存在数据竞争。
至于z++和y=1,二者操作的是不同内存位置,不存在冲突,所以它们之间的happens-before关系不影响数据竞争的判定。
内容的提问来源于stack exchange,提问作者Jia Cheng Sun
相关产品推荐
相关产品推荐

