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 既不可複製(copyable)也不可移動(movable)。
|
<stdatomic.h> 中提供了相容性巨集 當包含 <stdatomic.h> 時,命名空間 |
(自 C++23 起) |
目錄 |
[編輯] 特化
[編輯] 主樣板
主 std::atomic 樣板可以用任何同時滿足 可複製建構 和 可複製賦值 的 可平凡複製 型別 T 來實體化。如果以下任何值為 false,則程式為非良構(ill-formed):
- 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> 中的型別定義(typedefs)所需的任何額外整數型別。
此外,產生的 std::atomic<Integral> 特化具有標準佈局、平凡預設建構子、(直到 C++20)及平凡解構子。有號整數算術定義為使用二補數;不會產生未定義的結果。
浮點數型別的特化當使用任一無 cv 修飾(cv-unqualified)的浮點數型別(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 的部分特化中。
[編輯] 成員函式
| 建構原子物件 (公開成員函式) | |
| 將值儲存到原子物件中 (公開成員函式) | |
| 檢查原子物件是否為無鎖(lock-free) (公開成員函式) | |
| 以原子方式用非原子引數取代原子物件的值 (公開成員函式) | |
| 以原子方式取得原子物件的值 (公開成員函式) | |
| 從原子物件中載入值 (公開成員函式) | |
| 以原子方式取代原子物件的值並取得先前持有的值 (公開成員函式) | |
| 以原子方式將原子物件的值與非原子引數進行比較,如果相等則執行原子交換,如果不等則執行原子載入 (公開成員函式) | |
| (C++20) |
阻塞執行緒直到收到通知且原子值發生變化 (公開成員函式) |
| (C++20) |
通知至少一個在該原子物件上等待的執行緒 (公開成員函式) |
| (C++20) |
通知所有在該原子物件上阻塞等待的執行緒 (公開成員函式) |
常數 | |
| [靜態] (C++17) |
指示該型別是否總為無鎖 (公開靜態成員常數) |
[編輯] 特化的成員函式
針對整數、浮點數(自 C++20 起)及指標型別的特化 | |
| 以原子方式將引數加到原子物件中存儲的值,並取得先前持有的值 (公開成員函式) | |
| 以原子方式從原子物件中存儲的值減去引數,並取得先前持有的值 (公開成員函式) | |
| 對原子值進行加法或減法 (公開成員函式) | |
僅針對整數及指標型別的特化 | |
| (C++26) |
以原子方式在引數與原子物件的值之間執行 std::max 並取得先前持有的值 (公開成員函式) |
| (C++26) |
以原子方式在引數與原子物件的值之間執行 std::min 並取得先前持有的值 (公開成員函式) |
| 將原子值遞增或遞減一 (公開成員函式) | |
僅針對整數型別的特化 | |
| 以原子方式在引數與原子物件的值之間執行位元 AND 並取得先前持有的值 (公開成員函式) | |
| 以原子方式在引數與原子物件的值之間執行位元 OR 並取得先前持有的值 (公開成員函式) | |
| 以原子方式在引數與原子物件的值之間執行位元 XOR 並取得先前持有的值 (公開成員函式) | |
| 對原子值執行位元 AND、OR、XOR (公開成員函式) | |
[編輯] 型別別名
為 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 是一個關鍵字,用於在 C 語言中提供原子型別。
建議實作確保在 C 中 _Atomic(T) 的表示方式與 C++ 中對於每個可能的型別 T 的 std::atomic<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) |
原子弱指標 (類別樣板特化) |
| 關於 原子型別 的 C 語言文件
| |