原子型別
目錄 |
[編輯] 語法
_Atomic ( type-name ) |
(1) | (C11 起) | |||||||
_Atomic type-name |
(2) | (C11 起) | |||||||
const
、volatile
和 restrict
混合使用,但與其他限定符不同,type-name 的原子版本可能具有不同的尺寸、對齊方式和物件表示。型別名稱 | - | 除陣列或函式以外的任何型別。對於 (1),type-name 也不能是原子型別或 cvr 限定的 |
標頭檔案 <stdatomic.h> 定義了許多便利的類型別名,從 atomic_bool 到 atomic_uintmax_t,它們簡化了此關鍵字與內建型別和庫型別的使用。
_Atomic const int* p1; // p is a pointer to an atomic const int const atomic_int* p2; // same const _Atomic(int)* p3; // same
如果編譯器定義了宏常量 __STDC_NO_ATOMICS__,則不提供關鍵字 _Atomic。
[編輯] 解釋
原子型別物件是唯一不受資料競爭影響的物件;也就是說,它們可以由兩個執行緒併發修改,或者由一個執行緒修改並由另一個執行緒讀取。
每個原子物件都有其自己的相關修改順序,這是對該物件所做的修改的完全排序。如果從某個執行緒的角度來看,對某個原子 M
的修改 A
先於對同一原子 M
的修改 B
發生,則在 M
的修改順序中,A
出現在 B
之前。
請注意,儘管每個原子物件都有其自己的修改順序,但沒有單一的完全順序;不同的執行緒可能以不同的順序觀察對不同原子物件的修改。
所有原子操作都保證有四種一致性:
- 寫-寫一致性:如果修改原子物件
M
的操作A
先於修改M
的操作B
發生,則A
在M
的修改順序中出現在B
之前。 - 讀-讀一致性:如果原子物件
M
的值計算A
先於M
的值計算B
發生,並且A
從M
上的副作用X
獲取其值,則B
計算出的值要麼是X
儲存的值,要麼是M
上的副作用Y
儲存的值,其中Y
在M
的修改順序中出現在X
之後。 - 讀-寫一致性:如果原子物件
M
的值計算A
先於對M
的操作B
發生,則A
從M
上的副作用X
獲取其值,其中X
在M
的修改順序中出現在B
之前。 - 寫-讀一致性:如果原子物件
M
上的副作用X
先於M
的值計算B
發生,則評估B
從X
或從在M
的修改順序中出現在X
之後的副作用Y
獲取其值。
一些原子操作也是同步操作;它們可能具有額外的釋放語義、獲取語義或順序一致語義。參見 memory_order。
內建的增量和減量運算子以及複合賦值是具有完全順序一致排序(如同使用 memory_order_seq_cst)的讀-改-寫原子操作。如果需要較不嚴格的同步語義,則可以使用標準庫函式。
原子屬性僅對左值表示式有意義。左值到右值轉換(它模擬從原子位置到 CPU 暫存器的記憶體讀取)會剝離原子性以及其他限定符。
本節不完整 原因:更多,審查與 memory_order 和原子庫頁面的互動 |
[編輯] 注意
訪問原子結構體/聯合體的成員是未定義行為。
庫型別 sig_atomic_t 不提供執行緒間同步或記憶體排序,只提供原子性。
volatile
型別不提供執行緒間同步、記憶體排序或原子性。
建議實現確保 C 中 _Atomic(T) 的表示與 C++ 中 std::atomic<T> 的表示對於每種可能的型別 T
都相同。用於確保原子性和記憶體排序的機制應該相容。
[編輯] 關鍵字
[編輯] 示例
#include <stdatomic.h> #include <stdio.h> #include <threads.h> atomic_int acnt; int cnt; int f(void* thr_data) { for (int n = 0; n < 1000; ++n) { ++cnt; ++acnt; // for this example, relaxed memory order is sufficient, e.g. // atomic_fetch_add_explicit(&acnt, 1, memory_order_relaxed); } return 0; } int main(void) { thrd_t thr[10]; for (int n = 0; n < 10; ++n) thrd_create(&thr[n], f, NULL); for (int n = 0; n < 10; ++n) thrd_join(thr[n], NULL); printf("The atomic counter is %u\n", acnt); printf("The non-atomic counter is %u\n", cnt); }
可能的輸出
The atomic counter is 10000 The non-atomic counter is 8644
[編輯] 參考文獻
- C23 標準 (ISO/IEC 9899:2024)
- 6.7.2.4 原子型別說明符 (p: TBD)
- 7.17 原子操作 <stdatomic.h> (p: TBD)
- C17 標準 (ISO/IEC 9899:2018)
- 6.7.2.4 原子型別說明符 (p: 87)
- 7.17 原子 <stdatomic.h> (p: 200-209)
- C11 標準 (ISO/IEC 9899:2011)
- 6.7.2.4 原子型別說明符 (p: 121)
- 7.17 原子操作 <stdatomic.h> (p: 273-286)
[編輯] 另請參見
併發支援庫 | |
C++ 文件 針對 atomic
|