namespace std {
class thread;
}
概要
クラスthreadは、新しい実行のスレッド(thread of execution)(以下、単にスレッドとする)の作成/待機/その他操作を行う機構を提供する。
threadオブジェクトとスレッドとの関係性
threadオブジェクトとスレッドは1:1の関係で対応づけられるが、両者は同一ではないことに留意。threadコンストラクタによって新しく作成されたスレッドは、そのthreadオブジェクトに関係付けられる。
threadコンストラクタでは新しいスレッドを1つ作成し、同コンストラクタを呼び出したスレッドはそのまま後続処理を続ける。一方で、新しいスレッド上ではthreadコンストラクタに与えた関数オブジェクトが呼び出される。つまりプログラム内に複数のスレッドが存在し、並行にそれぞれの処理を行うことが可能な状態となる。なお、複数のスレッドが真に並行実行されるか否かは処理系に依存する。(たとえばDual Core環境で4つのスレッドを作成することはできるが、ハードウェアの制約から同時処理されるのは2スレッド以下に制限される。)
新しいスレッド上で呼び出される関数オブジェクトから例外が送出された場合、std::terminate()関数が呼び出されてプログラムは終了する。この動作が好ましくないのであれば、同関数オブジェクトから外に例外送出されないことをプログラマが保証しなければならない。
また、デフォルト構築されたthreadオブジェクトは、何も指さない空のthreadオブジェクトとなる。
join操作とdetach操作
threadオブジェクトとスレッドが関連付けられた状態では、threadオブジェクトのメンバ関数join()を介してそのスレッド完了を待機することができる(join操作)。メンバ関数join()が呼び出された時点でthreadオブジェクトに関連付けられたスレッドがまだ処理継続中だった場合、その対象スレッドが完了するまで呼び出し元スレッドがブロックされる。このjoin操作が終わったthreadオブジェクトは、何も指さない空のthreadオブジェクトとなる。
またthreadオブジェクトのメンバ関数detach()により、threadオブジェクトとスレッドの関連付けを切ることもできる(detach操作)。detach操作がなされたスレッドは、それ以後は他スレッドから直接関与することが出来なくなる。またdetach操作が終わったthreadオブジェクトは、何も指さない空のthreadオブジェクトとなる。
threadオブジェクトを破棄するデストラクタでは、そのthreadオブジェクトが何も指していないことが要件となっている。言い換えると、新しいスレッドを作成したthreadオブジェクトでは、破棄される前にjoin操作またはdetach操作のいずれか一方が必ず行われなければならない。この要件に反した場合、threadオブジェクトのデストラクタはstd::terminate()関数を呼び出してプログラム終了する。
メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(constructor) |
コンストラクタ | C++11 |
(destructor) |
デストラクタ | C++11 |
operator= |
代入演算子 | C++11 |
swap |
別のthreadと交換する |
C++11 |
joinable |
スレッドに関連付けられているか否かを取得する | C++11 |
join |
スレッドが終了するまで待機する | C++11 |
detach |
スレッドの管理を手放す | C++11 |
get_id |
関連付けられているスレッドのスレッド識別子を取得する | C++11 |
native_handle |
スレッドに関連付けられたネイティブハンドルを取得する[処理系定義] | C++11 |
静的メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
hardware_concurrency |
処理系によりサポートされるスレッド並行数を取得する | C++11 |
メンバ型
| 名前 | 説明 | 対応バージョン |
|---|---|---|
id |
スレッド識別子 (class) | C++11 |
native_handle_type |
ネイティブハンドル型 (type-alias)[処理系定義] | C++11 |
非メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
swap |
2つのthreadオブジェクトを入れ替える |
C++11 |
備考
型native_handle_typeおよびメンバ関数native_handleについて、同メンバの存在有無およびその意味は処理系定義となる。
例
#include <cassert>
#include <thread>
int main()
{
int x = 0, y = 0;
std::thread t([&]{ ++x; });
--y;
t.join();
assert(x == 1 && y == -1);
return 0;
}
出力
バージョン
言語
- C++11
処理系
- Clang: ??
- GCC: 4.7.0 ✅
- ICC: ??
- Visual C++: 2012 ✅, 2013 ✅, 2015 ✅
- 2012はメモリリークするバグあり link