最終更新日時: 2026年07月22日 16時08分23秒 (JST)
rotarymars が更新

履歴 編集

class
<thread>

# std::jthread(C++20)

    namespace std {
      class jthread;
    }

## 概要

クラス`jthread`は、`thread`と同じく、新しい実行のスレッド(thread of execution)（以下、単にスレッドとする）の作成／待機／その他操作を行う機構を提供する。このクラスはさらに、実行しているスレッドに対する停止要求を扱う機能や、自動で`join`操作を行う機能を提供する。

## `thread`クラスとの違い

- 停止要求のサポート: `jthread`は自身と関連付けられたスレッドに対する停止要求を扱う仕組みを提供する。このために`<stop_token>`ヘッダに定義されたクラスを利用する。
- 自動join機能: `jthread`はデストラクタやムーブ代入演算子が呼び出されたとき、もし自身に関連付けられたスレッドが存在する場合は、スレッドの停止要求を作成し、その後`join()`を呼び出してスレッドの終了を待機する。そのため`thread`クラスと異なり、`joinable() == true` であってもデストラクタやムーブ代入演算子を呼び出し可能であり、`std::terminate()`は呼び出されない。

## メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++20
`(destructor)` | デストラクタ | C++20
`operator=` | 代入演算子 | C++20
`swap` | 別の`jthread`と交換する | C++20
`joinable` | スレッドに関連付けられているか否かを取得する | C++20
`join` | スレッドが終了するまで待機する | C++20
`detach` | スレッドの管理を手放す | C++20
`get_id` | 関連付けられているスレッドのスレッド識別子を取得する | C++20
`native_handle` | スレッドに関連付けられたネイティブハンドルを取得する［処理系定義］ | C++20
`get_stop_source` | 停止要求を作成するための`stop_source`オブジェクトを取得する | C++20
`get_stop_token` | 停止状態を問い合わせるための`stop_token`オブジェクトを取得する | C++20
`request_stop` | スレッドに対する停止要求を作成する | C++20

## 静的メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`hardware_concurrency` | 処理系によりサポートされるスレッド並行数を取得する | C++20

## メンバ型

名前 | 説明 | 対応バージョン
--- | --- | ---
`id` | スレッド識別子 (type-alias) | C++20
`native_handle_type` | ネイティブハンドル型 (type-alias)［処理系定義］ | C++20

## 非メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`swap` | 2つの`jthread`オブジェクトを入れ替える | C++20

## 備考

- 型`native_handle_type`およびメンバ関数`native_handle`について、同メンバの存在有無およびその意味は処理系定義となる。
- 型`id`および型`native_handle_type`は、`thread`クラスで定義しているものと同じものを使用する。

## 例

### 基本的な使い方

    #include <iostream>
    #include <cstdint>
    #include <thread>
    #include <chrono>

    std::uint64_t sum1 = 0;
    std::uint64_t sum2 = 0;

    void f1(std::stop_token stoken, std::uint64_t n)
    {
      sum1 = 0;
      for (std::uint64_t i = 1; i < n; ++i) {
        if (stoken.stop_requested()) {
          // 中断リクエストがきたのでスレッドを終了する
          break;
        }
        sum1 += i;
      }
    }

    void f2(std::uint64_t n)
    {
      sum2 = 0;
      for (std::uint64_t i = 1; i < n; ++i) {
        sum2 += i;
      }
    }

    int main()
    {
      {
        // 関数の第1引数がstd::stop_token型である場合、
        // スレッドに中断リクエストを送れるようになる
        std::jthread jt1 {f1, 1'000'000};
        std::this_thread::sleep_for(std::chrono::milliseconds{3});
        jt1.request_stop(); // スレッドの中断要求を発行

        // スレッド実行する関数がstd::stop_tokenを受け取らない場合、
        // 中断リクエストを使用せず、
        // デストラクタで自動的にjoinするスレッドオブジェクトとして使用する
        std::jthread jt2 {
          [] { f2(1'000'000); }
        };
      } // jthreadのデストラクタでは、中断要求を発行し、スレッドの終了を待機する

      std::cout << sum1 << std::endl; // 計算できたところまで表示
      std::cout << sum2 << std::endl;
    }

#### 出力例

    48458670270
    499999500000

### stop_callbackと組み合わせる例

    #include <cassert>
    #include <thread>
    #include <stop_token>

    int main()
    {
      int x = 0, y = 0;

      std::jthread jt([&](std::stop_token st) { x++; });

      // スレッドに対する停止要求の作成に合わせて呼び出される
      // コールバックを定義する。
      std::stop_callback sc { jt.get_stop_token(), [&] { y++; }};

      assert(y == 0);

      // 明示的にjoin()を呼び出さずにtを上書きする。
      // このとき、ムーブ代入演算子の呼び出しの中で、
      // 自動で停止要求の作成とjoin()の呼び出しが行われる。
      jt = std::jthread{};

      assert(x == 1 && y == 1);

      return 0;
    }

#### 出力

## バージョン

### 言語

- C++20

### 処理系

- Clang:
- GCC: 10.2.0 ✅
- Visual C++: ??