# std::atomic

< cpp‎ | 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) /* see below */ | (5) | (C++23 起)

每个 `std::atomic` 模板的实例化和全特化定义一个原子类型。若一个线程写入原子对象，同时另一线程从它读取，则行为良好定义（数据竞争的细节见内存模型）。

另外，对原子对象的访问可以建立线程间同步，并按 std::memory_order 所对非原子内存访问定序。

`std::atomic` 既不可复制亦不可移动。

兼容性宏 `_Atomic` 于头文件 `<stdatomic.h>` 中提供，使得两者均良构时 _Atomic(T) 等同于 std::atomic<T> 。 未指定包含 `<stdatomic.h>` 时命名空间 `std` 中的任何声明可用。 | (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

std::atomic<bool> 使用初等模板。它保证是标准布局结构体。

#### 部分特化

标准库为下列类型提供 `std::atomic` 模板的特化，它们拥有初等模板所不拥有的额外属性：

2) 对所有指针类型的部分特化 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<Integral>` 特化拥有标准布局、平凡默认构造函数 (C++20 前)和平凡析构函数。定义有符号整数算术为使用补码；无未定义结果。

#### 对浮点类型的特化 以浮点类型 float 、 double 和 long double 之一实例化时， `std::atomic` 提供适合于浮点类型的额外原子操作，例如 `fetch_add` 和 `fetch_sub` 。 另外，结果的 `std::atomic<Floating>` 特化拥有标准布局和平凡析构函数。 无操作导致未定义行为，即使结果不能以浮点类型表示。有效的浮点环境可能不同于调用方线程的浮点环境。 | (C++20 起)

### 类型别名

为 bool 和所有上面列出的整数类型提供如下类型别名：

##### 所有 `std::atomic<Integral>` 别名
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` 才有定义。

`std::atomic_signed_lock_free` 与 `std::atomic_unsigned_lock_free` 在自立实现中可选。 | (C++20 起)

### 成员类型

成员类型 | 定义
`value_type` | `T` (无论是否特化)
`difference_type` | `value_type` (仅对 `atomic<Integral>` 和 `atomic<Floating>` (C++20 起) 特化) std::ptrdiff_t (仅对 `atomic<U*>` 特化)

`difference_type` 不在初等 `atomic` 模板中，或不在对 std::shared_ptr 和 std::weak_ptr 的部分特化中定义。

### 成员函数

(构造函数) | 构造原子对象 (公开成员函数)
operator= | 存储值于原子对象 (公开成员函数)
is_lock_free | 检查原子对象是否免锁 (公开成员函数)
store | 原子地以非原子对象替换原子对象的值 (公开成员函数)
load | 原子地获得原子对象的值 (公开成员函数)
operator T | 从原子对象加载值 (公开成员函数)
exchange | 原子地替换原子对象的值并获得它先前持有的值 (公开成员函数)
compare_exchange_weak compare_exchange_strong | 原子地比较原子对象与非原子参数的值，若相等则进行交换，若不相等则进行加载 (公开成员函数)
wait (C++20) | 阻塞线程直至被提醒且原子值更改 (公开成员函数)
notify_one (C++20) | 提醒至少一个在原子对象上的等待中阻塞的线程 (公开成员函数)
notify_all (C++20) | 提醒所有在原子对象上的等待中阻塞的线程 (公开成员函数)
### 常量
is_always_lock_free [静态] (C++17) | 指示该类型是否始终免锁 (公开静态成员常量)

### 特化成员函数

fetch_add | 原子地将参数加到存储于原子对象的值，并返回先前保有的值 (公开成员函数)
fetch_sub | 原子地从存储于原子对象的值减去参数，并获得先前保有的值 (公开成员函数)
fetch_and | 原子地进行参数和原子对象的值的逐位与，并获得先前保有的值 (公开成员函数)
fetch_or | 原子地进行参数和原子对象的值的逐位或，并获得先前保有的值 (公开成员函数)
fetch_xor | 原子地进行参数和原子对象的值的逐位异或，并获得先前保有的值 (公开成员函数)
operator++operator++(int)operator--operator--(int) | 令原子值增加或减少一 (公开成员函数)
operator+=operator-=operator&=operator|=operator^= | 加、减，或与原子值进行逐位与、或、异或 (公开成员函数)

### 注解

存在等价于 `std::atomic` 所有成员函数的非成员函数模板。这些非成员函数可以额外对非 std::atomic 特化的类型重载，但不能保证原子性。标准库中仅有的这种类型是 std::shared_ptr<U> 。

C 中 `_Atomic` 是关键词并用于提供原子类型。

推荐实现确保对于每个可能的类型 `T` ， C 中 _Atomic(T) 的表示与 C++ 中 std::atomic<T> 的相同。用于确保原子性与内存顺序的机制应该兼容。

gcc 和 clang 上，此处描述的某些功能要求通过 `-latomic` 链接。

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 2441 | C++11 | 可选的定宽整数类型的原子版本的 typedef 缺失 | 已添加
P0558R1 | C++11 | 某些原子类型函数的模板实参推导可能意外失败； 提供了非法指针操作 | 实质上重写了规范： 提供了成员 typedef `value_type` 与 `difference_type`
LWG 3012 | C++11 | `std::atomic<T>` 对任何可平凡复制但非可复制的 `T` 容许 | 禁止这种特化

### 参阅

atomic_flag (C++11) | 免锁的布尔原子类型 (类)
std::atomic<std::shared_ptr> (C++20) | 原子共享指针 (类模板特化)
std::atomic<std::weak_ptr> (C++20) | 原子弱指针 (类模板特化)