アトミック型
目次 |
[編集] 構文
_Atomic ( 型名 ) |
(1) | (C11 以降) | |||||||
_Atomic 型名 |
(2) | (C11 以降) | |||||||
const、volatile、および restrict と混在させることができます。ただし、他の修飾子とは異なり、型名 のアトミックバージョンは、サイズ、アラインメント、およびオブジェクト表現が異なる場合があります。| 型名 | - | 配列型または関数型以外の任意の型。 (1) の場合、型名 はアトミック型または 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 よりも前に現れます。
各アトミックオブジェクトには独自の変更順序がありますが、単一の合計順序は存在しないことに注意してください。異なるスレッドは、異なるアトミックオブジェクトへの変更を異なる順序で観測する可能性があります。
すべての原子操作で保証される 4 つのコヒーレンス種類があります。
- 書き込み-書き込みコヒーレンス: アトミックオブジェクト
Mを変更する操作Aが、Mを変更する操作Bよりも *先行している* 場合、AはMの変更順序でBよりも前に現れます。 - 読み取り-読み取りコヒーレンス: アトミックオブジェクト
Mの値計算AがMの値計算Bよりも先行し、AがMに対する副作用Xから値を取得する場合、Bによって計算された値は、Xによって格納された値、またはMに対する副作用Y(`X` よりも `M` の変更順序で後に現れる)によって格納された値のいずれかです。 - 読み取り-書き込みコヒーレンス: アトミックオブジェクト
Mの値計算Aが、Mに対する操作Bよりも *先行している* 場合、AはMに対する副作用Xから値を取得し、XはMの変更順序でBよりも前に現れます。 - 書き込み-読み取りコヒーレンス: アトミックオブジェクト
Mに対する副作用XがMの値計算Bよりも *先行している* 場合、Bの評価はXから値を取得するか、またはMの変更順序でXよりも後に現れる副作用Yから値を取得します。
一部のアトミック操作は同期操作でもあり、追加のリリースセマンティクス、アquireセマンティクス、または順序整合セマンティクスを持つ場合があります。memory_order を参照してください。
組み込みの インクリメントおよびデクリメント演算子 および 複合代入 は、全体的な順序整合順序付け(memory_order_seq_cst を使用する場合と同様)を持つ読み取り-変更-書き込みアトミック操作です。それほど厳密でない同期セマンティクスが必要な場合は、代わりに 標準ライブラリ関数 を使用できます。
アトミックプロパティは、lvalue 式に対してのみ意味があります。lvalue から rvalue への変換(アトミック場所から CPU レジスタへのメモリ読み取りをモデル化します)は、他の修飾子とともにアトミック性を剥奪します。
| このセクションは未完成です 理由: memory_order および atomic ライブラリページとの相互作用をさらにレビューする必要があります。 |
[編集] 注記
アトミックな構造体/共用体のメンバーへのアクセスは未定義の動作です。
ライブラリ型 sig_atomic_t は、アトミック性のみを提供し、スレッド間同期やメモリ順序付けは提供しません。
volatile 型は、スレッド間同期、メモリ順序付け、またはアトミック性を提供しません。
実装は、C における _Atomic(T) の表現が、すべての可能な型 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標準 (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 について) |