はじめに
C++の std::thread
オブジェクトは、生成されると特定のスレッドの実行を管理します。この thread
オブジェクトに対して、スレッドの終了を待つ .join()
や、スレッドを切り離す .detach()
を呼び出すと、オブジェクトはスレッドの管理を手放し、「空」の状態になります。
.joinable()
メソッドは、thread
オブジェクトが現在、有効なスレッドを管理しているかどうかを調べるためのものです。joinable()
が true
を返すオブジェクトに対してのみ、.join()
や .detach()
を安全に呼び出すことができます。
この記事では、joinable()
の基本的な使い方と、thread
オブジェクトのライフサイクルにおけるその役割の重要性について解説します。
joinable()
の状態変化を確認するサンプルコード
このコードは、thread
オブジェクトを生成した直後、.join()
を呼び出した後、そしてムーブ代入した後の、joinable()
の戻り値がどのように変化するかを示します。
完成コード
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
// スレッドで実行する簡単なタスク
void short_task() {
this_thread::sleep_for(chrono::milliseconds(100));
}
int main() {
// 1. スレッドを生成
thread worker(short_task);
// 2. joinable()の確認 (生成直後)
// workerは有効なスレッドを管理しているため、trueを返す
cout << "生成直後 -> worker.joinable(): " << boolalpha << worker.joinable() << endl;
// 3. スレッドの終了を待つ
worker.join();
// 4. joinable()の確認 (join()呼び出し後)
// workerはスレッドの管理を手放したため、falseを返す
cout << "join()後 -> worker.joinable(): " << boolalpha << worker.joinable() << endl;
// NG: joinableでないスレッドにjoin()を呼ぶと、プログラムがクラッシュする
// if (worker.joinable()) {
// worker.join();
// }
return 0;
}
boolalpha
: C++のストリームマニピュレータで、bool
値を 1
/0
ではなく true
/false
の文字列として出力させます。
コードの解説と joinable()
の重要性
joinable()
が true
を返す条件
thread
オブジェクトが、まだ.join()
も.detach()
も呼び出されていない、アクティブなスレッドを管理している。- デフォルトコンストラクタで作られた空の
thread
オブジェクトではない。 - 他の
thread
オブジェクトに**ムーブ(所有権を移動)**させていない。
joinable()
が false
を返す条件
.join()
が既に呼び出された後。.detach()
が既に呼び出された後。- デフォルトコンストラクタで生成された
thread
オブジェクト。 - 他の
thread
オブジェクトにムーブした後の、元のオブジェクト。
デストラクタと joinable()
の関係
thread
オブジェクトは、そのデストラクタ(オブジェクトが破棄されるとき)が呼び出される際に、自身が joinable()
であるかどうかをチェックします。
もし、joinable()
が true
の状態(つまり、有効なスレッドを管理しているのに、join
も detach
もされていない状態)でオブジェクトが破棄されると、デストラクタは std::terminate()
を呼び出し、プログラム全体を即座に強制終了させます。
これは、管理されていないスレッドが宙ぶらりんになるのを防ぐための、C++の安全機構です。したがって、thread
オブジェクトを生成したら、そのスコープを抜ける前に必ず join()
または detach()
を呼び出す必要があります。
まとめ
今回は、std::thread::joinable()
メソッドの役割について解説しました。
joinable()
は、そのthread
オブジェクトが.join()
や.detach()
を呼び出せる状態か (true
)、そうでないか (false
) を返す。joinable()
がtrue
のままthread
オブジェクトを破棄すると、プログラムが強制終了する。- したがって、
thread
を生成したら、破棄する前に必ずjoin()
またはdetach()
を呼び出さなければならない。
joinable()
を直接 if
文などで使う場面は少ないかもしれませんが、このメソッドが true
を返す状態の意味を理解することは、std::thread
のライフサイクルを正しく管理し、安全なマルチスレッドプログラムを書く上で非常に重要です。