std::memory_order_consume在C++20被弃用,因其数据依赖语义难以被编译器正确实现,主流编译器均将其降级为acquire,导致行为不可靠且无实际优化收益。

std::memory_order_consume 为什么在 C++20 被标记为 deprecated?
因为它的语义太难正确实现,且几乎没有编译器真正按标准要求支持它。C++ 标准委员会在 C++20 中将其标记为 deprecated,不是因为它“没用”,而是因为它的使用成本远高于收益——几乎所有实际代码都该改用 std::memory_order_acquire。
它和 std::memory_order_acquire 的关键区别在哪?
std::memory_order_consume 本意是只对“数据依赖链”上的读操作施加顺序约束(data-dependency ordering),而 std::memory_order_acquire 是对所有后续读写都加屏障(acquire barrier)。这意味着:
- 理论上,
consume允许编译器做更多优化(比如重排不依赖的访存) - 但实际上,主流编译器(GCC、Clang、MSVC)为简化实现,**一律将
consume当作acquire处理** - 即使硬件支持(如 Alpha),编译器也很难在 IR 层精确跟踪“数据依赖”——尤其是经过内联、SROA、LTO 后,依赖关系可能被破坏或隐藏
你写了 consume,但实际得到的是 acquire
这段代码看似用了 consume:
std::atomicptr{nullptr}; std::atomic ready{false}; // 线程 A int data = 42; ptr.store(&data, std::memory_order_relaxed); ready.store(true, std::memory_order_release);
// 线程 B while (!ready.load(std::memory_order_consume)) { / spin / } int p = ptr.load(std::memory_order_consume); // ← 这里期望依赖约束 int value = p; // ← 依赖于 p,应被 consume 保护
但 GCC/Clang 实际生成的汇编和 acquire 完全一致;更糟的是,如果编译器误判依赖(例如把 *p 提前到 load 之前,或因优化消除间接访问),consume 就无法阻止重排——而你根本不会收到警告。
立即学习“C++免费学习笔记(深入)”;
- Clang 自 3.6 起默认将
consume降级为acquire - GCC 从 5.0 开始同样如此,且文档明确说 “not implemented as specified”
- MSVC 直接忽略
consume,始终用acquire
现在该怎么做?
直接替换。所有原本用 std::memory_order_consume 的地方,统一改为 std::memory_order_acquire(写端对应用 std::memory_order_release):
- 行为更可预测,所有编译器都按标准严格执行
- 性能差异在绝大多数场景下可忽略(现代 CPU 的 acquire/release 几乎无额外开销)
- 避免未来升级编译器后出现未定义行为(C++23 已移除
consume的规范语义) - 如果你真在写 OS 内核或极低延迟系统,并且明确控制编译器和硬件(如仅用特定版本 GCC + ARM64),那需单独验证——但这种情况极少
真正难的从来不是选哪个 memory order,而是确认数据依赖是否真的存在、是否被编译器看见。而 consume 把这个确认责任推给了程序员,却没给任何工具辅助验证——这才是它被弃用的核心原因。











