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> 时,命名空间 |
(自 C++23 起) |
内容 |
[编辑] 特化
[编辑] 主模板
主 std::atomic
模板可以使用任何满足 TriviallyCopyable 类型 T
实例化,且该类型同时满足 CopyConstructible 和 CopyAssignable。如果以下任何值是 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::is_same<T, typename std::remove_cv<T>::type>::value
struct Counters { int a; int b; }; // user-defined trivially-copyable type std::atomic<Counters> cnt; // specialization for the user-defined type
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<Integral>
特化具有标准布局、平凡默认构造函数、(直到 C++20) 和平凡析构函数。有符号整数算术运算定义为使用补码;没有未定义的结果。
浮点型类型的特化当使用 cv 限定的浮点型类型(float、double、long double 和 cv 限定的 扩展浮点型类型(自 C++23 起))实例化时, 此外,生成的 即使结果在浮点型类型中不可表示,也没有操作会导致未定义行为。生效的 浮点环境 可能与调用线程的浮点环境不同。 |
(自 C++20 起) |
[编辑] 成员类型
类型 | 定义 | ||||
value_type
|
T (无论是否特化) | ||||
difference_type [1] |
|
- ↑
difference_type
未在主std::atomic
模板或 std::shared_ptr 和 std::weak_ptr 的部分特化中定义。
[编辑] 成员函数
构造一个原子对象 (公共成员函数) | |
将值存储到原子对象中 (公共成员函数) | |
检查原子对象是否是无锁的 (公共成员函数) | |
原子地用非原子实参替换原子对象的值 (公共成员函数) | |
原子地获取原子对象的值 (公共成员函数) | |
从原子对象加载值 (公共成员函数) | |
原子地替换原子对象的值并获取先前持有的值 (公共成员函数) | |
原子地将原子对象的值与非原子实参进行比较,如果相等则执行原子交换,否则执行原子加载 (公共成员函数) | |
(C++20) |
阻塞线程直到收到通知且原子值发生更改 (公共成员函数) |
(C++20) |
通知至少一个等待原子对象的线程 (公共成员函数) |
(C++20) |
通知所有阻塞等待原子对象的线程 (公共成员函数) |
常量 | |
[静态] (C++17) |
指示类型是否始终是无锁的 (公共静态成员常量) |
[编辑] 特化成员函数
为整型、浮点型、浮点型(自 C++20 起) 和指针类型特化 | |
原子地将实参加到原子对象中存储的值,并获取先前持有的值 (公共成员函数) | |
原子地从原子对象中存储的值减去实参,并获取先前持有的值 (公共成员函数) | |
加到或减去原子值 (公共成员函数) | |
仅为整型和指针类型特化 | |
(C++26) |
原子地执行实参与原子对象值之间的 std::max,并获取先前持有的值 (公共成员函数) |
(C++26) |
原子地执行实参与原子对象值之间的 std::min,并获取先前持有的值 (公共成员函数) |
将原子值递增或递减 1 (公共成员函数) | |
仅为整型特化 | |
原子地执行实参与原子对象值之间的按位与,并获取先前持有的值 (公共成员函数) | |
原子地执行实参与原子对象值之间的按位或,并获取先前持有的值 (公共成员函数) | |
原子地执行实参与原子对象值之间的按位异或,并获取先前持有的值 (公共成员函数) | |
执行与原子值的按位与、或、异或 (公共成员函数) |
[编辑] 类型别名
为 bool 和上面列出的所有整型类型提供类型别名,如下所示
所有
| |
atomic_bool (C++11) |
std::atomic<bool> (类型定义) |
atomic_char (C++11) |
std::atomic<char> (类型定义) |
atomic_schar (C++11) |
std::atomic<signed char> (类型定义) |
atomic_uchar (C++11) |
std::atomic<unsigned char> (类型定义) |
atomic_short (C++11) |
std::atomic<short> (类型定义) |
atomic_ushort (C++11) |
std::atomic<unsigned short> (类型定义) |
atomic_int (C++11) |
std::atomic<int> (类型定义) |
atomic_uint (C++11) |
std::atomic<unsigned int> (类型定义) |
atomic_long (C++11) |
std::atomic<long> (类型定义) |
atomic_ulong (C++11) |
std::atomic<unsigned long> (类型定义) |
atomic_llong (C++11) |
std::atomic<long long> (类型定义) |
atomic_ullong (C++11) |
std::atomic<unsigned long long> (类型定义) |
atomic_char8_t (C++20) |
std::atomic<char8_t> (类型定义) |
atomic_char16_t (C++11) |
std::atomic<char16_t> (类型定义) |
atomic_char32_t (C++11) |
std::atomic<char32_t> (类型定义) |
atomic_wchar_t (C++11) |
std::atomic<wchar_t> (类型定义) |
atomic_int8_t (C++11)(可选) |
std::atomic<std::int8_t> (类型定义) |
atomic_uint8_t (C++11)(可选) |
std::atomic<std::uint8_t> (类型定义) |
atomic_int16_t (C++11)(可选) |
std::atomic<std::int16_t> (类型定义) |
atomic_uint16_t (C++11)(可选) |
std::atomic<std::uint16_t> (类型定义) |
atomic_int32_t (C++11)(可选) |
std::atomic<std::int32_t> (类型定义) |
atomic_uint32_t (C++11)(可选) |
std::atomic<std::uint32_t> (类型定义) |
atomic_int64_t (C++11)(可选) |
std::atomic<std::int64_t> (类型定义) |
atomic_uint64_t (C++11)(可选) |
std::atomic<std::uint64_t> (类型定义) |
atomic_int_least8_t (C++11) |
std::atomic<std::int_least8_t> (类型定义) |
atomic_uint_least8_t (C++11) |
std::atomic<std::uint_least8_t> (类型定义) |
atomic_int_least16_t (C++11) |
std::atomic<std::int_least16_t> (类型定义) |
atomic_uint_least16_t (C++11) |
std::atomic<std::uint_least16_t> (类型定义) |
atomic_int_least32_t (C++11) |
std::atomic<std::int_least32_t> (类型定义) |
atomic_uint_least32_t (C++11) |
std::atomic<std::uint_least32_t> (类型定义) |
atomic_int_least64_t (C++11) |
std::atomic<std::int_least64_t> (类型定义) |
atomic_uint_least64_t (C++11) |
std::atomic<std::uint_least64_t> (类型定义) |
atomic_int_fast8_t (C++11) |
std::atomic<std::int_fast8_t> (类型定义) |
atomic_uint_fast8_t (C++11) |
std::atomic<std::uint_fast8_t> (类型定义) |
atomic_int_fast16_t (C++11) |
std::atomic<std::int_fast16_t> (类型定义) |
atomic_uint_fast16_t (C++11) |
std::atomic<std::uint_fast16_t> (类型定义) |
atomic_int_fast32_t (C++11) |
std::atomic<std::int_fast32_t> (类型定义) |
atomic_uint_fast32_t (C++11) |
std::atomic<std::uint_fast32_t> (类型定义) |
atomic_int_fast64_t (C++11) |
std::atomic<std::int_fast64_t> (类型定义) |
atomic_uint_fast64_t (C++11) |
std::atomic<std::uint_fast64_t> (类型定义) |
atomic_intptr_t (C++11)(可选) |
std::atomic<std::intptr_t> (类型定义) |
atomic_uintptr_t (C++11)(可选) |
std::atomic<std::uintptr_t> (类型定义) |
atomic_size_t (C++11) |
std::atomic<std::size_t> (类型定义) |
atomic_ptrdiff_t (C++11) |
std::atomic<std::ptrdiff_t> (类型定义) |
atomic_intmax_t (C++11) |
std::atomic<std::intmax_t> (类型定义) |
atomic_uintmax_t (C++11) |
std::atomic<std::uintmax_t> (类型定义) |
特殊用途类型的别名 | |
atomic_signed_lock_free (C++20) |
一种带符号的整型原子类型,它是无锁的,并且等待/通知效率最高 (类型定义) |
atomic_unsigned_lock_free (C++20) |
一种无符号的整型原子类型,它是无锁的,并且等待/通知效率最高 (类型定义) |
std::atomic_intN_t
、std::atomic_uintN_t
、std::atomic_intptr_t
和 std::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>。
_Atomic
是一个 keyword,用于在 C 语言中提供 原子类型。
建议实现确保在 C 语言中 _Atomic(T)
的表示与在 C++ 中 std::atomic<T>
的表示对于每种可能的类型 T
都是相同的。用于确保原子性和内存顺序的机制应该是兼容的。
在 GCC 和 Clang 上,此处描述的某些功能需要链接 -latomic
。
特性测试宏 | 值 | 标准 | 特性 |
---|---|---|---|
__cpp_lib_atomic_ref |
201806L |
(C++20) | std::atomic_ref
|
__cpp_lib_constexpr_atomic |
202411L |
(C++26) | constexpr std::atomic 和 std::atomic_ref |
[编辑] 示例
#include <atomic> #include <iostream> #include <thread> #include <vector> std::atomic_int acnt; int cnt; void f() { for (auto n{10000}; n; --n) { ++acnt; ++cnt; // Note: for this example, relaxed memory order is sufficient, // e.g. 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 << "The atomic counter is " << acnt << '\n' << "The non-atomic counter is " << cnt << '\n'; }
可能的输出
The atomic counter is 100000 The non-atomic counter is 69696
[编辑] 缺陷报告
以下行为变更缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
LWG 2441 | C++11 | 可选的固定宽度整数类型的原子版本的类型定义缺失 固定宽度整数类型 缺失 |
已添加 |
LWG 3012 | C++11 | std::atomic<T> 允许用于任何 T 即可平凡复制但不可复制的类型 |
禁止此类特化 |
LWG 3949 | C++17 | 要求 std::atomic<bool> 具有 平凡析构函数的措辞在 C++17 中意外删除 |
已添加回 |
LWG 4069 (P3323R1) |
C++11 | 对 cv 限定的 T 的支持存在疑问 |
不允许 T 为 cv 限定的 |
P0558R1 | C++11 | 某些原子类型函数的模板参数推导可能 意外失败;提供了无效的指针操作 失败;提供了无效的指针操作 |
规范已大幅重写 已添加成员类型定义 value_type 和 difference_type |
[编辑] 参见
(C++11) |
无锁布尔原子类型 (类) |
(C++20) |
原子共享指针 (类模板特化) |
(C++20) |
原子弱指针 (类模板特化) |