C++ std::atomic_ref

2025 年 2 月 11 日 | 阅读 4 分钟

C++ 函数 std::atomic_ref 是一个用于安全、无锁并发编程的有效工具。它是在 C++20 引入 C++ 标准库时包含的。由于此类别为原子对象提供了类似引用的接口,因此无需显式锁定技术(如互斥锁),并允许多个线程安全地访问和修改共享数据。尽管 std::atomic 直接管理原子对象,但 std::atomic_ref 对预先存在的非原子变量进行操作,从而为其提供原子访问。因此,在处理遗留代码或无法直接更改变量类型以使其原子化的场景中,它特别有用。

Std::atomic_ref 的重要优势在于,它在不不必要地牺牲性能的情况下强制执行原子性保证。为了确保有效并发访问共享数据,它尽可能利用硬件对原子操作的支持。借助 std::atomic_ref,程序员可以创建安全有效的并发代码,从而减少数据竞争的可能性,并确保多线程环境中的一致行为。

在它引用的对象上,std::atomic_ref 类模板执行原子操作。std::atomic_ref 引用的对象在其生命周期内被视为原子对象。有关数据竞争的更多信息,请参阅内存模型。如果一个线程写入原子对象,而另一个线程从中读取,则行为是明确定义的。此外,原子对象访问能够创建线程间同步,并根据 std::memory_order 提供的规范安排非原子内存访问。

所有引用对象的 std::atomic_ref 实例的生命周期必须长于对象本身。即使存在任何引用对象的 std::atomic_ref 实例,对象也只能通过这些 std::atomic_ref 实例访问。任何 std::atomic_ref 对象的子对象都不得同时被任何其他 std::atomic_ref 对象引用。

在头文件 <atomic> 中定义

声明 std::atomic_ref

如果我们要使用 std::atomic_ref 函数,请包含 <atomic> 头文件。

语法

它具有以下语法:

参数

  • Type:它是共享变量的类型。
  • shared_var:它是要原子化访问的共享变量。

示例 1

让我们举一个例子来说明 C++ 中的 std::atomic_ref()

输出

 
Final coordinates: (30000, 30000)   

说明

  • 在此示例中,我们定义了一个包含两个整数成员 x 和 y 的基本 Point 结构。
  • 对于原子访问,我们创建了一个名为 atomicPointstd::atomic_ref 和一个名为 point 的 Point 实例。
  • 在 lambda 函数 modifyPoint 中,每个线程迭代地增加 atomicPoint 的 x 和 y 坐标。
  • 创建多个线程以同时更改 Point 结构。
  • 每个线程将 x 和 y 增加 10,000 次,因此一旦所有线程都完成运行,我们打印 Point 结构的最终坐标,该坐标应为 (30000, 30000)。

示例 2

让我们再举一个例子来说明 C++ 中的 std::atomic_ref()

输出

 
Final counter value: 40000   

说明

  • 在此示例中,我们的计数器变量的初始值为 0。
  • 我们构造一个 atomicCounter std::atomic_ref 以允许对计数器进行原子访问。
  • 每个线程在 lambda 函数 incrementCounter 内部反复将 atomicCounter 增加 1。
  • 同时递增计数器需要创建多个线程。
  • 一旦每个线程都完成了其执行,我们使用 atomicCounter 对象输出计数器的最终值。

结论

在 C++ 中,std::atomic_ref 提供了一种有效的机制来允许安全、无锁并发编程。它通过为原子对象提供类似引用的接口来实现这一点,这消除了对互斥锁等显式锁定技术的需要,并允许多个线程安全地访问和修改共享数据。在处理遗留代码或无法直接更改变量类型以使其原子化的场景中,此功能特别有用。std::atomic_ref 利用硬件对原子操作的支持来保证对共享数据的有效并发访问。通过利用它,程序员可以创建安全有效的并发代码,从而减少数据竞争的可能性,并确保多线程设置中的一致行为。