std::atomic
| 
 在标头  
<atomic> 定义 | 
||
| 
 template< class T > 
struct atomic;  | 
(1) | (C++11 起) | 
| 
 template< class U > 
struct atomic<U*>;  | 
(2) | (C++11 起) | 
| 
 在标头  
<memory> 定义 | 
||
| 
 template<class U> 
struct atomic<std::shared_ptr<U>>;  | 
(3) | (C++20 起) | 
| 
 template<class U> 
struct atomic<std::weak_ptr<U>>;  | 
(4) | (C++20 起) | 
| 
 在标头  
<stdatomic.h> 定义 | 
||
| 
 #define _Atomic(T) /* 见下文 */ 
 | 
(5) | (C++23 起) | 
每个 std::atomic 模板的实例化和全特化均定义一个原子类型。如果一个线程写入原子对象,同时另一线程从它读取,那么行为有良好定义(数据竞争的细节见内存模型)。
另外,对原子对象的访问可以建立线程间同步,并按 std::memory_order 对非原子内存访问定序。
std::atomic 既不可复制也不可移动。
| 
 在 <stdatomic.h> 中提供了兼容性宏  包含 <stdatomic.h> 时未指定命名空间   | 
(C++23 起) | 
特化
主模板
主 std::atomic 模板可用任何满足可复制构造 (CopyConstructible) 及可复制赋值 (CopyAssignable) 的可平凡复制 (TriviallyCopyable) 类型 T 实例化。如果下列任何值是 false,那么程序非良构:
- std::is_trivially_copyable<T>::value
 - std::is_copy_constructible<T>::value
 - std::is_move_constructible<T>::value
 - std::is_copy_assignable<T>::value
 - std::is_move_assignable<T>::value
 
struct Counters { int a; int b; }; // 用户定义的可平凡复制类型 std::atomic<Counters> cnt; // 为用户定义的类型而特化
std::atomic<bool> 使用的是主模板。它保证是标准布局结构体,并且具有平凡析构函数。
部分特化
标准库为下列类型提供 std::atomic 模板的特化,它们拥有主模板所不拥有的额外属性:
std::atomic<U*>。这些特化拥有标准布局、平凡默认构造函数 (C++20 前)和平凡析构函数。除了为所有原子类型提供的操作外,这些特化额外支持适合指针类型的原子算术运算,例如 fetch_add、fetch_sub。| 
 3,4) 针对 std::shared_ptr 和 std::weak_ptr 提供的部分特化 std::atomic<std::shared_ptr<U>> 和 std::atomic<std::weak_ptr<U>>。 
细节见 std::atomic<std::shared_ptr> 和 std::atomic<std::weak_ptr>。  | 
(C++20 起) | 
对整数类型的特化
以下列整数类型之一实例化时,std::atomic 提供适合于整数类型的额外原子操作,例如 fetch_add、fetch_sub、fetch_and、fetch_or、fetch_xor:
- 
- 字符类型 char、char8_t (C++20 起)、char16_t、char32_t 和 wchar_t;
 - 标准有符号整数类型:signed char、short、int、long 和 long long;
 - 标准无符号整数类型:unsigned char、unsigned short、unsigned int、unsigned long 和 unsigned long long;
 - 标头 <cstdint> 中的各 typedef 所需的任何额外整数类型。
 
 
另外,结果的 std::atomic<整数> 特化拥有标准布局、平凡默认构造函数 (C++20 前)和平凡析构函数。定义有符号整数算术为使用补码;无未定义的结果。
对浮点类型的特化以无 cv 限定的浮点类型(float、double、long double 和无 cv 限定的扩展浮点类型 (C++23 起))之一实例化时, 另外,结果的  无操作导致未定义行为,即使结果不能以浮点类型表示。有效的浮点环境可能与调用方线程的浮点环境不同。  | 
(C++20 起) | 
成员类型
| 成员类型 | 定义 | 
value_type | 
T (无论是否特化) | 
difference_type | 
value_type (仅对 atomic<整数> 和 atomic<浮点> (C++20 起) 特化)std::ptrdiff_t (仅对 std::atomic<U*> 特化) | 
std::atomic 主模板中,或对 std::shared_ptr 和 std::weak_ptr 的部分特化中,未定义 difference_type。
成员函数
| 构造原子对象 (公开成员函数)  | 
|
| 存储值于原子对象 (公开成员函数)  | 
|
| 检查原子对象是否免锁 (公开成员函数)  | 
|
| 原子地以非原子实参替换原子对象的值 (公开成员函数)  | 
|
| 原子地获得原子对象的值 (公开成员函数)  | 
|
| 从原子对象加载值 (公开成员函数)  | 
|
| 原子地替换原子对象的值并获得它先前持有的值 (公开成员函数)  | 
|
| 原子地比较原子对象与非原子实参的值,相等时进行原子交换,不相等时进行原子加载 (公开成员函数)  | 
|
| 
 (C++20) 
 | 
阻塞线程直到被提醒且原子值更改 (公开成员函数)  | 
| 
 (C++20) 
 | 
提醒至少一个在原子对象上的等待中阻塞的线程 (公开成员函数)  | 
| 
 (C++20) 
 | 
提醒所有在原子对象上的等待中阻塞的线程 (公开成员函数)  | 
常量 | 
|
| 
 [静态] (C++17) 
 | 
指示该类型是否始终免锁 (公开静态成员常量)  | 
特化成员函数
为整数、浮点 (C++20 起)和指针类型特化 | 
|
| 原子地将实参加到存储于原子对象的值上,并返回先前保有的值 (公开成员函数)  | 
|
| 原子地从存储于原子对象的值减去实参,并获得先前保有的值 (公开成员函数)  | 
|
| 与原子值进行加、减 (公开成员函数)  | 
|
仅为整数和指针类型特化 | 
|
| 
 (C++26) 
 | 
原子地进行实参和原子对象的值的 std::max,并获得先前保有的值 (公开成员函数)  | 
| 
 (C++26) 
 | 
原子地进行实参和原子对象的值的 std::min,并获得先前保有的值 (公开成员函数)  | 
| 令原子值增加或减少一 (公开成员函数)  | 
|
仅为整数类型特化 | 
|
| 原子地进行实参和原子对象的值的逐位与,并获得先前保有的值 (公开成员函数)  | 
|
| 原子地进行实参和原子对象的值的逐位或,并获得先前保有的值 (公开成员函数)  | 
|
| 原子地进行实参和原子对象的值的逐位异或,并获得先前保有的值 (公开成员函数)  | 
|
| 与原子值进行逐位与、或、异或 (公开成员函数)  | 
|
类型别名
为 bool 和所有上面列出的整数类型提供如下类型别名:
所有 
 | 
|
| 
 atomic_bool 
(C++11) 
 | 
std::atomic<bool> (typedef)  | 
| 
 atomic_char 
(C++11) 
 | 
std::atomic<char> (typedef)  | 
| 
 atomic_schar 
(C++11) 
 | 
std::atomic<signed char> (typedef)  | 
| 
 atomic_uchar 
(C++11) 
 | 
std::atomic<unsigned char> (typedef)  | 
| 
 atomic_short 
(C++11) 
 | 
std::atomic<short> (typedef)  | 
| 
 atomic_ushort 
(C++11) 
 | 
std::atomic<unsigned short> (typedef)  | 
| 
 atomic_int 
(C++11) 
 | 
std::atomic<int> (typedef)  | 
| 
 atomic_uint 
(C++11) 
 | 
std::atomic<unsigned int> (typedef)  | 
| 
 atomic_long 
(C++11) 
 | 
std::atomic<long> (typedef)  | 
| 
 atomic_ulong 
(C++11) 
 | 
std::atomic<unsigned long> (typedef)  | 
| 
 atomic_llong 
(C++11) 
 | 
std::atomic<long long> (typedef)  | 
| 
 atomic_ullong 
(C++11) 
 | 
std::atomic<unsigned long long> (typedef)  | 
| 
 atomic_char8_t 
(C++20) 
 | 
std::atomic<char8_t> (typedef)  | 
| 
 atomic_char16_t 
(C++11) 
 | 
std::atomic<char16_t> (typedef)  | 
| 
 atomic_char32_t 
(C++11) 
 | 
std::atomic<char32_t> (typedef)  | 
| 
 atomic_wchar_t 
(C++11) 
 | 
std::atomic<wchar_t> (typedef)  | 
| 
 atomic_int8_t 
(C++11)(可选) 
 | 
std::atomic<std::int8_t> (typedef)  | 
| 
 atomic_uint8_t 
(C++11)(可选) 
 | 
std::atomic<std::uint8_t> (typedef)  | 
| 
 atomic_int16_t 
(C++11)(可选) 
 | 
std::atomic<std::int16_t> (typedef)  | 
| 
 atomic_uint16_t 
(C++11)(可选) 
 | 
std::atomic<std::uint16_t> (typedef)  | 
| 
 atomic_int32_t 
(C++11)(可选) 
 | 
std::atomic<std::int32_t> (typedef)  | 
| 
 atomic_uint32_t 
(C++11)(可选) 
 | 
std::atomic<std::uint32_t> (typedef)  | 
| 
 atomic_int64_t 
(C++11)(可选) 
 | 
std::atomic<std::int64_t> (typedef)  | 
| 
 atomic_uint64_t 
(C++11)(可选) 
 | 
std::atomic<std::uint64_t> (typedef)  | 
| 
 atomic_int_least8_t 
(C++11) 
 | 
std::atomic<std::int_least8_t> (typedef)  | 
| 
 atomic_uint_least8_t 
(C++11) 
 | 
std::atomic<std::uint_least8_t> (typedef)  | 
| 
 atomic_int_least16_t 
(C++11) 
 | 
std::atomic<std::int_least16_t> (typedef)  | 
| 
 atomic_uint_least16_t 
(C++11) 
 | 
std::atomic<std::uint_least16_t> (typedef)  | 
| 
 atomic_int_least32_t 
(C++11) 
 | 
std::atomic<std::int_least32_t> (typedef)  | 
| 
 atomic_uint_least32_t 
(C++11) 
 | 
std::atomic<std::uint_least32_t> (typedef)  | 
| 
 atomic_int_least64_t 
(C++11) 
 | 
std::atomic<std::int_least64_t> (typedef)  | 
| 
 atomic_uint_least64_t 
(C++11) 
 | 
std::atomic<std::uint_least64_t> (typedef)  | 
| 
 atomic_int_fast8_t 
(C++11) 
 | 
std::atomic<std::int_fast8_t> (typedef)  | 
| 
 atomic_uint_fast8_t 
(C++11) 
 | 
std::atomic<std::uint_fast8_t> (typedef)  | 
| 
 atomic_int_fast16_t 
(C++11) 
 | 
std::atomic<std::int_fast16_t> (typedef)  | 
| 
 atomic_uint_fast16_t 
(C++11) 
 | 
std::atomic<std::uint_fast16_t> (typedef)  | 
| 
 atomic_int_fast32_t 
(C++11) 
 | 
std::atomic<std::int_fast32_t> (typedef)  | 
| 
 atomic_uint_fast32_t 
(C++11) 
 | 
std::atomic<std::uint_fast32_t> (typedef)  | 
| 
 atomic_int_fast64_t 
(C++11) 
 | 
std::atomic<std::int_fast64_t> (typedef)  | 
| 
 atomic_uint_fast64_t 
(C++11) 
 | 
std::atomic<std::uint_fast64_t> (typedef)  | 
| 
 atomic_intptr_t 
(C++11)(可选) 
 | 
std::atomic<std::intptr_t> (typedef)  | 
| 
 atomic_uintptr_t 
(C++11)(可选) 
 | 
std::atomic<std::uintptr_t> (typedef)  | 
| 
 atomic_size_t 
(C++11) 
 | 
std::atomic<std::size_t> (typedef)  | 
| 
 atomic_ptrdiff_t 
(C++11) 
 | 
std::atomic<std::ptrdiff_t> (typedef)  | 
| 
 atomic_intmax_t 
(C++11) 
 | 
std::atomic<std::intmax_t> (typedef)  | 
| 
 atomic_uintmax_t 
(C++11) 
 | 
std::atomic<std::uintmax_t> (typedef)  | 
特殊用途类型的别名 | 
|
| 
 atomic_signed_lock_free 
(C++20) 
 | 
免锁且对于等待/提醒最高效的有符号整数原子类型 (typedef)  | 
| 
 atomic_unsigned_lock_free 
(C++20) 
 | 
免锁且对于等待/提醒最高效的无符号整数原子类型 (typedef)  | 
注意:std::atomic_intN_t、std::atomic_uintN_t、std::atomic_intptr_t 和 atomic_uintptr_t 分别在当且仅当定义了 std::intN_t、std::uintN_t、std::intptr_t 和 std::uintptr_t 时才会有定义。
| 
 
  | 
(C++20 起) | 
注解
存在等价于 std::atomic 所有成员函数的非成员函数模板。这些非成员函数可以额外对非 std::atomic 特化的类型重载,但不能保证原子性。标准库中仅有的这种类型是 std::shared_ptr<U>。
推荐实现确保对于每个可能的类型 T,C 中 _Atomic(T) 的表示与 C++ 中 std::atomic<T> 的相同。用于确保原子性与内存定序的机制应该兼容。
gcc 和 clang 上,此处描述的某些功能要求通过 -latomic 链接。
示例
#include <atomic> #include <iostream> #include <thread> #include <vector> std::atomic_int acnt; int cnt; void f() { for (int n = 0; n < 10000; ++n) { ++acnt; ++cnt; // 注意: 对于此示例,宽松内存定序已经足够, // 例如 acnt.fetch_add(1, std::memory_order_relaxed); } } int main() { { std::vector<std::jthread> pool; for (int n = 0; n < 10; ++n) pool.emplace_back(f); } std::cout << "原子计数器为 " << acnt << '\n' << "非原子计数器为 " << cnt << '\n'; }
可能的输出:
原子计数器为 100000 非原子计数器为 69696
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 | 
|---|---|---|---|
| LWG 2441 | C++11 | 可选的定宽整数类型的原子版本的 typedef 缺失 | 已添加 | 
| LWG 3012 | C++11 | std::atomic<T> 对任何可平凡复制但非可复制的 T 容许 | 
禁止这种特化 | 
| LWG 3949 | C++17 | C++17 意外地丢失了要求 std::atomic<bool> 具有平凡析构函数的说明 | 已补回 | 
| P0558R1 | C++11 | 某些原子类型函数的模板实参推导可能意外失败; 提供了非法指针操作  | 
实质上重写了规范:提供成员 typedefvalue_type 和 difference_type | 
参阅
| 
 (C++11) 
 | 
免锁的布尔原子类型 (类)  | 
| 
 (C++20) 
 | 
原子共享指针 (类模板特化)  | 
| 
 (C++20) 
 | 
原子弱指针 (类模板特化)  |