std::atomic++_ref 是 c++20 中用于对非原子类型变量进行原子操作的模板类。1. 它允许临时以原子方式访问非原子变量,而无需将其声明为 std::atomic
std::atomic_ref 是 C++20 中引入的一个新特性,它的作用是让你对一个原本非原子类型的变量进行原子操作,而无需将该变量本身定义为 std::atomic
这个特性在多线程编程中非常有用,尤其是在你想对某些共享数据进行原子操作,但又不希望或不能将其声明为原子类型的情况下。
什么是 std::atomic_ref?
std::atomic_ref
立即学习“C++免费学习笔记(深入)”;
举个例子:
int x = 0; std::atomic_ref<int> ref(x); ref.store(42, std::memory_order_relaxed);
上面这段代码让变量 x 在被 atomic_ref 引用时,可以进行原子操作。但要注意:多个线程同时通过不同的 atomic_ref 修改同一个变量是未定义行为(UB),必须确保只有一个线程在使用 atomic_ref 进行写操作。
使用场景和限制
常见用途:
- 对结构体中的某个字段做原子更新。
- 与第三方库交互时,对方提供了非原子变量,但你希望安全地并发访问。
- 避免因为使用 std::atomic
而带来的内存对齐或性能开销。
限制条件:
- 所引用的对象必须具有合适的对齐方式(通常需要是 T 的自然对齐)。
- 同一时间只能有一个线程通过 atomic_ref 修改对象。
- 不建议长期持有 atomic_ref 实例,应该在需要的时候构造并立即使用。
对内存模型的影响
使用 std::atomic_ref 时,你需要指定内存顺序(如 memory_order_relaxed, memory_order_acquire 等),这些顺序会影响编译器和 CPU 的优化方式,进而影响程序的行为。
例如:
std::atomic_ref<int> ref(x); ref.fetch_add(1, std::memory_order_acq_rel);
这里用了 acq_rel,意味着:
- 操作前不会发生重排序(获取语义)。
- 操作后也不会让后续操作提前执行(释放语义)。
因此,使用 atomic_ref 时选择正确的 memory order 很重要,否则可能引发数据竞争或违反预期的同步行为。
使用注意事项
- 生命周期管理:确保 atomic_ref 所引用的对象在其生命周期内有效。
- 避免重复封装:不要把已经是一个 std::atomic
的变量再封装成 atomic_ref。 - 跨线程使用要小心:不同线程不应该同时用各自的 atomic_ref 修改同一变量。
- 对齐问题:有些平台对原子操作有严格的对齐要求,否则会崩溃或行为异常。
基本上就这些。std::atomic_ref 是一个强大但容易误用的工具,适用于特定的并发场景。掌握好它的使用规则,才能真正发挥它的价值。