Atomic types
目次 |
構文
_Atomic
(
type-name
)
|
(1) | (C11以降) | |||||||
_Atomic
type-name
|
(2) | (C11以降) | |||||||
const
、
volatile
、および
restrict
と組み合わせることができますが、他の修飾子とは異なり、
type-name
のアトミック版はサイズ、アライメント、オブジェクト表現が異なる場合があります。
| type-name | - | 配列または関数以外の任意の型。 (1) の場合、 type-name はアトミック型またはCV修飾型であってはならない |
ヘッダー <stdatomic.h> は 多数の便利な型エイリアス を定義しており、 atomic_bool から atomic_uintmax_t まで、組み込み型およびライブラリ型でのこのキーワードの使用を簡素化します。
_Atomic const int* p1; // pはatomic const intへのポインタ const atomic_int* p2; // 同上 const _Atomic(int)* p3; // 同上
コンパイラによってマクロ定数 __STDC_NO_ATOMICS__ が定義されている場合、キーワード _Atomic は提供されません。
説明
アトミック型のオブジェクトは、 データ競合 から解放された唯一のオブジェクトです。つまり、これらは2つのスレッドによって同時に変更されるか、1つのスレッドによって変更されながら別のスレッドによって読み取られる可能性があります。
各アトミックオブジェクトは、それ自身に関連付けられた
変更順序
を持ちます。これはそのオブジェクトに対して行われた変更の全順序です。もし、あるスレッドの観点から、あるアトミック
M
の変更
A
が同じアトミック
M
の変更
B
に対して
happens-before
の関係にあるならば、
M
の変更順序において、
A
は
B
よりも前に発生します。
各アトミックオブジェクトには独自の変更順序が存在しますが、単一の全順序は存在しないことに注意してください。異なるスレッドは、異なるアトミックオブジェクトへの変更を異なる順序で観察する可能性があります。
すべてのアトミック操作に対して保証される4つの一貫性の種類があります:
-
書き込み-書き込み一貫性
:アトミックオブジェクト
Mを変更する操作Aが、Mを変更する操作Bより 先行発生 する場合、Mの変更順序においてAはBより前に現れる。 -
読み取り-読み取り一貫性
:アトミックオブジェクト
Mの値計算AがMの値計算Bより先行発生し、かつAがMに対する副作用Xから値を取得する場合、Bによって計算される値は、Xによって格納された値、またはMの変更順序においてXより後に現れる副作用Yによって格納された値のいずれかである。 -
読み取り-書き込み一貫性
:アトミックオブジェクト
Mの値計算AがMに対する操作Bより 先行発生 する場合、AはMの変更順序においてBより前に現れる副作用Xから値を取得する。 -
書き込み-読み取り一貫性
:アトミックオブジェクト
Mに対する副作用XがMの値計算Bより 先行発生 する場合、評価BはXから、またはMの変更順序においてXより後に現れる副作用Yから値を取得する。
一部のアトミック操作は同期操作でもあります。これらは追加の解放セマンティクス、取得セマンティクス、または逐次一貫性セマンティクスを持つ場合があります。詳細は memory_order を参照してください。
組み込みの インクリメント・デクリメント演算子 および 複合代入演算子 は、完全な順次一貫性順序を持つ読み込み-変更-書き込みのアトミック操作です( memory_order_seq_cst を使用しているかのように)。より緩和された同期セマンティクスが必要な場合は、代わりに 標準ライブラリ関数 を使用できます。
アトミック性は lvalue式 に対してのみ意味を持ちます。lvalueからrvalueへの変換(アトミックなメモリ位置からCPUレジスタへのメモリ読み取りをモデル化)は、他の修飾子と共にアトミック性を取り除きます。
|
このセクションは不完全です
理由: 詳細な説明が必要、memory_orderとatomicライブラリページとの相互作用のレビュー |
注記
アトミックな構造体/共用体のメンバにアクセスすることは未定義動作です。
ライブラリ型 sig_atomic_t は、スレッド間同期やメモリ順序付けを提供せず、アトミック性のみを提供します。
volatile
型は、スレッド間の同期、メモリ順序付け、またはアトミック性を提供しません。
実装は、あらゆる可能な型
T
に対して、C言語の
_Atomic
(
T
)
の表現がC++の
std
::
atomic
<
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 standard (ISO/IEC 9899:2024):
-
- 6.7.2.4 Atomic type specifiers (p: TBD)
-
- 7.17 Atomics <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++ documentation
for
atomic
|