Namespaces
Variants

Atomic types

From cppreference.net

目次

翻訳の説明: - 「Contents」を「目次」に翻訳しました - HTMLタグ、属性、数値はそのまま保持しています - C++関連の用語(Syntax、Explanation、Notes、Keywords、Example、References、See also)は翻訳せずに原文のまま保持しています - すべての書式設定と構造は完全に保持されています

構文

_Atomic ( type-name ) (1) (C11以降)
_Atomic type-name (2) (C11以降)
1) 型指定子として使用する; これは新しいアトミック型を指定します
2) 型修飾子として使用;これは type-name のアトミック版を指定します。この役割では、 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つの一貫性の種類があります:

  1. 書き込み-書き込み一貫性 :アトミックオブジェクト M を変更する操作 A が、 M を変更する操作 B より 先行発生 する場合、 M の変更順序において A B より前に現れる。
  2. 読み取り-読み取り一貫性 :アトミックオブジェクト M の値計算 A M の値計算 B より先行発生し、かつ A M に対する副作用 X から値を取得する場合、 B によって計算される値は、 X によって格納された値、または M の変更順序において X より後に現れる副作用 Y によって格納された値のいずれかである。
  3. 読み取り-書き込み一貫性 :アトミックオブジェクト M の値計算 A M に対する操作 B より 先行発生 する場合、 A M の変更順序において B より前に現れる副作用 X から値を取得する。
  4. 書き込み-読み取り一貫性 :アトミックオブジェクト M に対する副作用 X M の値計算 B より 先行発生 する場合、評価 B X から、または M の変更順序において X より後に現れる副作用 Y から値を取得する。

一部のアトミック操作は同期操作でもあります。これらは追加の解放セマンティクス、取得セマンティクス、または逐次一貫性セマンティクスを持つ場合があります。詳細は memory_order を参照してください。

組み込みの インクリメント・デクリメント演算子 および 複合代入演算子 は、完全な順次一貫性順序を持つ読み込み-変更-書き込みのアトミック操作です( memory_order_seq_cst を使用しているかのように)。より緩和された同期セマンティクスが必要な場合は、代わりに 標準ライブラリ関数 を使用できます。

アトミック性は lvalue式 に対してのみ意味を持ちます。lvalueからrvalueへの変換(アトミックなメモリ位置からCPUレジスタへのメモリ読み取りをモデル化)は、他の修飾子と共にアトミック性を取り除きます。

注記

アトミックな構造体/共用体のメンバにアクセスすることは未定義動作です。

ライブラリ型 sig_atomic_t は、スレッド間同期やメモリ順序付けを提供せず、アトミック性のみを提供します。

volatile 型は、スレッド間の同期、メモリ順序付け、またはアトミック性を提供しません。

実装は、あらゆる可能な型 T に対して、C言語の _Atomic ( T ) の表現がC++の std :: atomic < T > と同じであることを保証することが推奨されます。アトミック性とメモリ順序を保証するために使用されるメカニズムは互換性があるべきです。

キーワード

_Atomic

#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)

関連項目

並行処理サポートライブラリ