C++多线程下语句原子性及atomic<double>操作的数据竞争疑问
C++多线程下的语句原子性与原子变量操作问题
1. 分号结尾的语句是否会作为整体执行?
不会。C++中,单条以分号结尾的语句并不具备天然的原子性。编译器会把语句拆解成若干条机器指令执行,在多线程环境下,这些指令可能被其他线程的执行打断,无法保证整个语句作为一个不可分割的单元完成。比如看似简单的int a = b + c;,实际会被拆成加载b、加载c、求和、赋值给a这几步,中间任何一步都可能被线程调度器抢占。
2. num.store(num.load() * 10)是否存在数据竞争风险?
是的,这里存在逻辑上的竞态条件(注:std::atomic的load和store本身都是原子操作,不会触发C++标准定义的“数据竞争”未定义行为,但操作的组合会导致逻辑错误)。
具体来说:
num.load()和num.store(...)是两个独立的原子操作,但它们的执行之间存在间隙。在load读取到值之后、store写入新值之前,其他线程完全可以修改num的内容。- 举个场景:线程A执行
num.load()得到3.1415,还没执行store;此时线程B将num修改为6.28;接着线程A把计算出的31.415写入num,直接覆盖了线程B的修改,导致数据丢失。
如果要实现原子的乘10操作,针对std::atomic<double>需要用CAS(比较并交换)循环来保证操作的原子性:
std::atomic<double> num{3.1415}; double expected = num.load(); while (!num.compare_exchange_weak(expected, expected * 10)) { // CAS失败时,expected会自动更新为当前num的最新值,继续重试 }
compare_exchange_weak会原子地完成“比较当前值与expected,相等则写入新值,否则更新expected”的操作,循环重试能确保最终的写入是基于最新的num值,避免其他线程的干扰。
内容的提问来源于stack exchange,提问作者PkDrew
相关产品推荐
相关产品推荐

