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

memory_order::acquire在read-modify-write操作中的作用与test_and_set疑问

关于std::atomic_flag::test_and_set使用memory_order::acquire的内存语义解析

首先明确核心结论:当test_and_set指定memory_order::acquire时,这个读改写(RMW)操作的加载部分遵循acquire语义,存储部分遵循relaxed语义——既不等同于memory_order::acq_rel,存储部分也不会默认使用seq_cst。

具体语义拆解

test_and_set本质是原子的"读取当前值 + 设置为true"操作:

  • 加载阶段(读取flag值):采用acquire语义,确保:
    • 临界区的所有代码不会被处理器重排到这个加载操作之前;
    • 当前线程能看到所有其他线程对该flag执行release语义操作(比如clear(release))之前的所有内存写入。
  • 存储阶段(设置flag为true):采用relaxed语义,仅保证该存储操作本身是原子的,不会对其他内存操作的顺序产生额外的同步约束——因为锁的"上锁"动作不需要向其他线程同步任何数据,只需要原子占据锁即可。

对疑问的澄清

  1. 是否等同于acq_rel?
    不是。memory_order::acq_rel要求RMW操作的加载部分是acquire,存储部分是release;而这里的存储是relaxed,没有release的同步效果。

  2. 存储部分是否默认用seq_cst?
    只有当你不指定内存序参数时,test_and_set才会默认使用memory_order::seq_cst。一旦显式指定了acquire,存储阶段就会遵循relaxed语义,而非seq_cst。

为什么锁场景这么用是合理的

在你的锁代码中:

std::atomic_flag lock;
// ...
while (lock.test_and_set(std::memory_order::acquire)) {}
// critical section
lock.clear(std::memory_order::release);
  • test_and_set(acquire)的acquire语义保证临界区能看到其他线程释放锁前的所有操作;
  • clear(release)的release语义负责把当前线程临界区的所有写入同步给后续获取锁的线程。
    这种搭配是标准的"acquire-release"锁实现,足够保证同步且比seq_cst性能更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:01:08