最終更新日時: 2025年10月10日 13時00分13秒 (JST)
Akira Takahashi が更新

履歴 編集

class template
<atomic>

# std::atomic(C++11)

    namespace std {
      template<class T> struct atomic;          // (1) C++11

      template<> struct atomic<integral>;       // (2) C++11
      template<> struct atomic<floating-point>; // (3) C++20
      template<class T> struct atomic<T*>;      // (4) C++11
    }

## 概要

`atomic`クラステンプレートは、型`T`をアトミック操作するためのクラステンプレートである。組み込み型に対する特殊化が提供されており、それぞれに特化した演算が用意されている。

- (1) : プライマリテンプレート。宣言のみ
- (2) : 整数型に対する特殊化
- (3) : (CV修飾されていない) 浮動小数点数型に対する特殊化
  - (C++23) : 拡張浮動小数点数型を含む
- (4) : 任意の型のポインタに対する特殊化

これらのほか、`<memory>`ヘッダで`std::shared_ptr`と`std::weak_ptr`に対する`atomic`クラスの特殊化が定義される。

## テンプレートパラメータ制約

- 型`T`はコピー構築可能かつコピー代入可能であること
- 以下のいずれかが`false`である場合、プログラムは不適格となる：
  - `is_trivially_copyable_v<T>`
    - 簡潔に言うと、`memcpy()`可能な型であること
  - `is_copy_constructible_v<T>`
  - `is_move_constructible_v<T>`
  - `is_copy_assignable_v<T>`
  - `is_move_assignable_v<T>`
  - C++26: `same_as<T, remove_cv_t<T>>`
    - CV修飾された`T`は許可しない

## 別名型

特殊化された整数型および`bool`型には、それぞれ`atomic_T`という型の別名が提供される。

名前付きアトミック型 | テンプレート引数となる整数型 | 対応バージョン
--- | --- | ---
`atomic_char` | `char` | C++11
`atomic_schar` | `signed char` | C++11
`atomic_uchar` | `unsigned char` | C++11
`atomic_short` | `short` | C++11
`atomic_ushort` | `unsigned short` | C++11
`atomic_int` | `int` | C++11
`atomic_uint` | `unsigned int` | C++11
`atomic_long` | `long` | C++11
`atomic_ulong` | `unsigned long` | C++11
`atomic_llong` | `long long` | C++11
`atomic_ullong` | `unsigned long long` | C++11
`atomic_char8_t` | `char8_t` | C++20
`atomic_char16_t` | `char16_t` | C++11
`atomic_char32_t` | `char32_t` | C++11
`atomic_wchar_t` | `wchar_t` | C++11
`atomic_bool` | `bool` | C++11

浮動小数点数型に対する別名は定義されていない。

また、`<cstdint>`で定義される整数型に対する以下の別名も提供される。

名前付きアトミック型 | テンプレート引数となる整数型 | 対応バージョン
--- | --- | ---
`atomic_int_least8_t` | `int_least8_t` | C++11
`atomic_uint_least8_t` | `uint_least8_t` | C++11
`atomic_int_least16_t` | `int_least16_t` | C++11
`atomic_uint_least16_t` | `uint_least16_t` | C++11
`atomic_int_least32_t` | `int_least32_t` | C++11
`atomic_uint_least32_t` | `uint_least32_t` | C++11
`atomic_int_least64_t` | `int_least64_t` | C++11
`atomic_uint_least64_t` | `uint_least64_t` | C++11
`atomic_int_fast8_t` | `int_fast8_t` | C++11
`atomic_uint_fast8_t` | `uint_fast8_t` | C++11
`atomic_int_fast16_t` | `int_fast16_t` | C++11
`atomic_uint_fast16_t` | `uint_fast16_t` | C++11
`atomic_int_fast32_t` | `int_fast32_t` | C++11
`atomic_uint_fast32_t` | `uint_fast32_t` | C++11
`atomic_int_fast64_t` | `int_fast64_t` | C++11
`atomic_uint_fast64_t` | `uint_fast64_t` | C++11
`atomic_size_t` | `size_t` | C++11
`atomic_ptrdiff_t` | `ptrdiff_t` | C++11
`atomic_intmax_t` | `intmax_t` | C++11
`atomic_uintmax_t` | `uintmax_t` | C++11

以下の整数型に対する別名は、整数型に対する`atomic`型の特殊化だが、その中でも以下の特性を持つものである：

- `is_always_lock_free`プロパティが`true`である
- wait/notify操作が最も効率的に行える整数アトミック型

ただし、フリースタンディング環境において、これらの型は定義されない場合がある。

名前付きアトミック型 | 説明 | 対応バージョン
--- | --- | ---
`atomic_signed_lock_free` | `is_always_lock_free == true`かつwait/notify操作が最も効率的に行える符号付き整数のアトミック型 | C++20
`atomic_unsigned_lock_free` | `is_always_lock_free == true`かつwait/notify操作が最も効率的に行える符号なし整数のアトミック型 | C++20

`<cstdint>`で定義される整数型に対する以下の別名は、元の整数型が定義される場合のみ定義される。

名前付きアトミック型 | テンプレート引数となる整数型 | 対応バージョン
--- | --- | ---
`atomic_int8_t` | `int8_t` | C++17
`atomic_uint8_t` | `uint8_t` | C++17
`atomic_int16_t` | `int16_t` | C++17
`atomic_uint16_t` | `uint16_t` | C++17
`atomic_int32_t` | `int32_t` | C++17
`atomic_uint32_t` | `uint32_t` | C++17
`atomic_int64_t` | `int64_t` | C++17
`atomic_uint64_t` | `uint64_t` | C++17
`atomic_intptr_t` | `intptr_t` | C++11
`atomic_uintptr_t` | `uintptr_t` | C++11

## メンバ関数

### 共通メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++11
`~atomic() = default` | デストラクタ | C++11
`operator=` | 代入演算子 | C++11
`is_lock_free` | オブジェクトがロックフリーに振る舞えるかを判定する | C++11
`store` | 値を書き込む | C++11
`load` | 値を読み込む | C++11
`operator T` | 型Tへの変換演算子 | C++11
`exchange` | 値を入れ替える | C++11
`compare_exchange_weak` | 弱い比較で値を入れ替える | C++11
`compare_exchange_strong` | 強い比較で値を入れ替える | C++11
`wait` | 起床されるまで待機する | C++20
`notify_one` | 待機しているスレッドをひとつ起床させる | C++20
`notify_all` | 待機している全てのスレッドを起床させる | C++20

### 共通メンバ型

名前 | 説明 | 対応バージョン
--- | --- | ---
`value_type` | 要素型となるテンプレートパラメータの型`T` | C++17

### 共通メンバ定数

名前 | 説明 | 対応バージョン
--- | --- | ---
`static constexpr bool is_always_lock_free` | 型`T`に対するアトミック操作が常にロックフリー (非ミューテックス) で動作する場合は`true`、そうでなければ`false` | C++17

`is_always_lock_free == true`の場合、このクラスのオブジェクトをシグナルハンドラー内で使用できる。

### atomic<integral>専用メンバ関数

整数型に対する特殊化。

名前 | 説明 | 対応バージョン
--- | --- | ---
`fetch_add` | 加算 | C++11
`fetch_sub` | 減算 | C++11
`fetch_and` | AND演算 | C++11
`fetch_or` | OR演算 | C++11
`fetch_xor` | XOR演算 | C++11
`fetch_max` | 最大値を設定・取得 | C++26
`fetch_min` | 最小値を設定・取得 | C++26
`store_add` | 値を読み込まずに加算 | C++26
`store_sub` | 値を読み込まずに減算 | C++26
`store_and` | 値を読み込まずにAND演算 | C++26
`store_or` | 値を読み込まずにOR演算 | C++26
`store_xor` | 値を読み込まずにXOR演算 | C++26
`store_max` | 値を読み込まずに最大値を設定 | C++26
`store_min` | 値を読み込まずに最小値を設定 | C++26
`operator++` | インクリメント | C++11
`operator--` | デクリメント | C++11
`operator+=` | 加算 | C++11
`operator-=` | 減算 | C++11
`operator&=` | AND演算 | C++11
`operator|=` | OR演算 | C++11
`operator^=` | XOR演算 | C++11

### atomic<integral>専用メンバ型

名前 | 説明 | 対応バージョン
--- | --- | ---
`difference_type` | 2つの値の差を表す整数型`value_type` | C++17

### atomic<floating-point>専用メンバ関数

浮動小数点数型に対する特殊化。

名前 | 説明 | 対応バージョン
--- | --- | ---
`fetch_add` | 加算 | C++20
`fetch_sub` | 減算 | C++20
`fetch_max` | 最大値を設定・取得 | C++26
`fetch_min` | 最小値を設定・取得 | C++26
`fetch_fmaximum` | 最大値を設定・取得 (`-0.0`と`+0.0`では`+0.0`、NaNと値ではNaNを返す) | C++26
`fetch_fminimum` | 最小値を設定・取得 (`-0.0`と`+0.0`では`-0.0`、NaNと値ではNaNを返す) | C++26
`fetch_fmaximum_num` | 最大値を設定・取得 (`-0.0`と`+0.0`では`+0.0`、NaNと値では数値を返す) | C++26
`fetch_fminimum_num` | 最小値を設定・取得 (`-0.0`と`+0.0`では`-0.0`、NaNと値では数値を返す) | C++26
`store_add` | 値を読み込まずに加算 | C++26
`store_sub` | 値を読み込まずに減算 | C++26
`store_and` | 値を読み込まずにAND演算 | C++26
`store_or` | 値を読み込まずにOR演算 | C++26
`store_xor` | 値を読み込まずにXOR演算 | C++26
`store_max` | 値を読み込まずに最大値を設定 | C++26
`store_min` | 値を読み込まずに最小値を設定 | C++26
`store_fmaximum` | 値を読み込まずに最大値を設定 (`-0.0`と`+0.0`では`+0.0`、NaNと値ではNaNを返す) | C++26
`store_fminimum` | 値を読み込まずに最小値を設定 (`-0.0`と`+0.0`では`-0.0`、NaNと値ではNaNを返す) | C++26
`store_fmaximum_num` |  | 値を読み込まずに最大値を設定 (`-0.0`と`+0.0`では`+0.0`、NaNと値では数値を返す)
`store_fminimum_num` | 値を読み込まずに最小値を設定 (`-0.0`と`+0.0`では`-0.0`、NaNと値では数値を返す) | C++26
`operator+=` | 加算 | C++20
`operator-=` | 減算 | C++20

### atomic<floating-point>専用メンバ型

名前 | 説明 | 対応バージョン
--- | --- | ---
`difference_type` | 2つの値の差を表す型`value_type` | C++20

### atomic<T*>専用メンバ関数

ポインタ型に対する特殊化。

名前 | 説明 | 対応バージョン
--- | --- | ---
`fetch_add` | 加算 | C++11
`fetch_sub` | 減算 | C++11
`fetch_max` | 最大値を設定・取得 | C++26
`fetch_min` | 最小値を設定・取得 | C++26
`store_add` | 値を読み込まずに加算 | C++26
`store_sub` | 値を読み込まずに減算 | C++26
`store_max` | 値を読み込まずに最大値を設定 | C++26
`store_min` | 値を読み込まずに最小値を設定 | C++26
`operator++` | インクリメント | C++11
`operator--` | デクリメント | C++11
`operator+=` | 加算 | C++11
`operator-=` | 減算 | C++11

### atomic<T*>専用メンバ型

名前 | 説明 | 対応バージョン
--- | --- | ---
`difference_type` | 2つの値の差を表す整数型`ptrdiff_t` | C++17

### 例

    // スピンロックの実装
    // Boost Atomic Library - Usage Example
    // http://www.boost.org/doc/libs/1_53_0/doc/html/atomic/usage_examples.html#boost_atomic.usage_examples.example_spinlock

    #include <iostream>
    #include <atomic>
    #include <thread>
    #include <mutex>

    class spinlock {
    private:
      enum LockState {Locked, Unlocked};
      std::atomic<LockState> state_;

    public:
      spinlock() : state_(Unlocked) {}

      void lock()
      {
        // 現在の状態をLockedと入れ替える
        while (state_.exchange(Locked, std::memory_order_acquire) == Locked) {
          // busy-wait...アンロックされるまで待機
        }
      }

      void unlock()
      {
        // 値をUnlockedに更新
        state_.store(Unlocked, std::memory_order_release);
      }
    };

    namespace {
      spinlock lock;
    }

    template <class T>
    void print(const T& x)
    {
      std::lock_guard<spinlock> lk(lock);
      std::cout << x << std::endl;
    }

    void f()
    {
      print(1);
    }

    void g()
    {
      print(2);
    }

    int main()
    {
      std::thread t1(f);
      std::thread t2(g);

      t1.join();
      t2.join();
    }

### 出力例

    2
    1

## バージョン

### 言語

- C++11

### 処理系

- Clang: 3.2 ✅
- GCC: 4.7.0 ✅
- Visual C++: 2012 ✅, 2013 ✅

### 備考

- GCC 4.9.2まで、アライメントがおかしくなってセグメンテーションフォルトになるバグがあった。GCC 5.1で修正された。(Bug 65147)

## 関連項目

- `std::shared_ptr`と`std::weak_ptr`に対する`atomic`クラスの特殊化

### 参照

- N2145 C++ Atomic Types and Operations
- N2547 Allow atomics use in signal handlers
- アトミックオブジェクトを含むクラスのコピーとムーブ - Faith and Brave - C++で遊ぼう
- LWG Issue 2441. Exact-width atomic `typedef`s should be provided
- P0558R1 Resolving `atomic<T>` named base class inconsistencies
- P0152R1 `constexpr atomic<T>::is_always_lock_free`
- P0020R6 Floating Point Atomic
- LWG Issue 3045. `atomic` doesn't have `value_type` or `difference_type`
- LWG Issue 3012. `atomic` is unimplementable for non-`is_trivially_copy_constructible T`
- Correctly implementing a spinlock in C++
- P1135R6 The C++20 Synchronization Library
  - C++20での`atomic_signed_lock_free`と`atomic_unsigned_lock_free`の追加
- P1467R9 Extended floating-point types and standard names
  - C++23で拡張浮動小数点数型もテンプレート引数として指定することが許可された
- P3323R1 cv-qualified types in `atomic` and `atomic_ref`
  - C++26でCV修飾されたテンプレートパラメータが明確に禁止された