C Language
アトミック
サーチ…
構文
-
#ifdef __STDC_NO_ATOMICS__
-
# error this implementation needs atomics
-
#endif
-
#include <stdatomic.h>
- 符号なし_Atomicカウンタ= ATOMIC_VAR_INIT(0);
備考
C言語の一部としてのAtomicsは、C11以降で使用可能なオプションの機能です。
それらの目的は、異なるスレッド間で共有される変数への競合のないアクセスを保証することです。原子修飾がなければ、2つのスレッドが同時にアクセスすると、共有変数の状態は未定義になります。例えば、インクリメント演算( ++
)は、いくつかのアセンブラ命令、読み出し、加算自体、およびストア命令に分割することができる。別のスレッドが同じ操作を行っている場合、その2つの命令シーケンスが絡み合い、矛盾した結果につながる可能性があります。
型:配列型を除くすべてのオブジェクト型は
_Atomic
で修飾できます。演算子:これらの演算子(
++
や*=
)は、すべて原子であることが保証されています。操作:型ジェネリック関数として指定される他の操作がいくつかあります(例:
atomic_compare_exchange
。スレッド:異なるスレッドからアクセスされた場合、それらにアクセスすることでデータ競合が発生しないことが保証されます。
シグナルハンドラ:原子タイプは、それらのすべての操作がステートレスであればロックフリーと呼ばれます 。この場合、通常の制御フローとシグナルハンドラの間で状態変化を処理するために使用することもできます。
ロックフリーであることが保証されているデータ型は
atomic_flag
です。これは、効率的なテストと設定のハードウェアの指示に対応する操作を行う最小限のタイプです。
競合状態を回避するための他の手段はC11のスレッドインタフェースで利用できます。特にスレッドが重要なデータやコードのクリティカルセクションにアクセスすることを相互に排除するmutex型のmtx_t
があります。アトミックが利用できない場合は、これらを使用してレースを防止する必要があります。
アトミックと演算子
競合条件を作成することなく、異なるスレッド間でアトミック変数に同時にアクセスできます。
/* a global static variable that is visible by all threads */
static unsigned _Atomic active = ATOMIC_VAR_INIT(0);
int myThread(void* a) {
++active; // increment active race free
// do something
--active; // decrement active race free
return 0;
}
基本型に対して許可されているすべての左辺演算(オブジェクトを変更する操作)は許可され、それらにアクセスする異なるスレッド間の競合条件につながりません。
- アトミックオブジェクトの操作は、通常、通常の算術演算よりも桁違いに遅くなります。これには、単純なロードまたはストア操作も含まれます。したがって、重要な作業にのみ使用してください。
-
a = a+1;
などの通常の算術演算と代入a = a+1;
実際には3つのオペレーションがa
ます。最初はロード、次に追加、最後にストアです。これはレースフリーではありません 。操作a += 1;
のみa += 1;
およびa++;
あります。