You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

原子对象读-改-写操作的Load是否保证读取修改顺序的最后值?

原子对象读-改-写操作的Load部分是否比普通Load操作更保证读取修改顺序中的最后值?
std::atomic<int> v = {0};

// 线程1:
for(int i = 0; i<999999;i++)
   v.load(memory_order::seq_cst);  // #1

v.exchange(2,memory_order::seq_cst);  // #2

// 线程2:
v.store(1,memory_order::seq_cst);  // #3

假设v的修改顺序为{0, 1},其中0是v的初始化写入值,1是线程2中#3的写入值,且#1和#2都不happens before #3。

根据[intro.races]第14~18条:

原子对象M在求值B中确定的值,由某个修改M的未指定副作用A存储,其中B不happens before A。
若修改原子对象M的操作A happens before 修改M的操作B,则A在M的修改顺序中早于B。
若原子对象M的值计算A happens before M的值计算B,且A从M上的副作用X取值,则B计算的值要么是X存储的值,要么是M上的副作用Y存储的值,其中Y在M的修改顺序中跟随X。
若原子对象M的值计算A happens before 修改M的操作B,则A从M上的副作用X取值,其中X在M的修改顺序中先于B。
若原子对象M上的副作用X happens before M的值计算B,则求值B从X或从M上的副作用Y取值,其中Y在M的修改顺序中跟随X。

#1处的普通Load操作允许在循环结束前始终读取0,也可以读取1。但根据[atomics.order]第10条:

Atomic read-modify-write operations shall always read the last value (in the modification order) written before the write associated with the read-modify-write operation.
(翻译:原子读-改-写操作必须读取其关联写入操作之前,修改顺序中的最后一个值。)

#2属于读-改-写操作,因此它的Load部分必须读取#3写入的1。

这种情况下,即使#1在循环中始终读取0,也不违反seq_cst的单一全序要求:

  • #1被sequenced before #2,这意味着#1strongly happens before #2,因此在单一全序中#1先于#2。
  • 由于#1读取0,而0在v的修改顺序中早于#3产生的1,根据[atomics.order]第3条:

某个原子对象M上的原子操作A被coherence-ordered before M上的另一个原子操作B,如果:

  • A是修改操作,且B读取A存储的值,或
  • [...]
  • A和B不是同一个原子读-改-写操作,且存在M的原子修改X,使得A读取X存储的值且X在M的修改顺序中先于B,或

#1被coherence-ordered before #3,因此在单一全序中#1先于#3。
最后,由于#2读取#3写入的值,#3被coherence-ordered before #2,因此在单一全序中#3先于#2。

这三个要求:

  1. #1 先于 #2
  2. #1 先于 #3
  3. #3 先于 #2

可以形成有效的单一全序{#1, #3, #2}。

综上,在给定前置条件下,#1可以始终加载0,而#2必须读取值1,这种情况是完全可能出现的。

内容的提问来源于stack exchange,提问作者xmh0511

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:05:21