thread
概要
C++11でスレッド関連のライブラリが追加された。追加された機能は、thread, mutex, スレッド同期(condition_variable), future/promiseパターンである。 ここでは、基本となるthreadクラスについて記述する。 C++11のthreadクラスはシンプルである。コンストラクタに別スレッドで処理させたい関数ポインタ、もしくは関数オブジェクトを指定するだけでスレッドが起動する。 引数を指定したい場合は、関数指定の後にそのまま記述すれば良い。 なお、threadクラスは実行した関数の戻り値は全て無視するため、実行結果を必要とする場合は別の方法で取得する必要が有る。
起動したスレッドは、必ずjoin()させなければならない。 規格策定中に暗黙的にjoin()する案も提案されていたが、意図しないバグを生み出す可能性があるとしてjoin()を必須としている。
本節で解説する機能を使用するには、ヘッダファイル threadをインクルードする。
以下に使用例を示す。
#include <thread>
void f() {}
struct func {
void operator() (int a, int b) {}
};
int main() {
std::thread t1(f); // 関数ポインタを指定
std::thread t2(func(), 1, 2); // 関数オブジェクトを指定
std::thread t3([](double a){
a = 1.0f;
},
0.0f); // 関数オブジェクト(lambda関数)を指定
t1.join();
t2.join();
t3.join();
return 0;
}
全てのスレッドにはユニークなが割り振られる。スレッドを起動した側では、threadクラスのget_id()を呼び出すことで取得できる。 スレッド内では、ネームスペースstd::this_threadに定義されたget_id()を呼び出すことで取得できる。 std::this_threadには他にも便利な関数が定義されている。以下に関数一覧を示す。
定義 | 効果 |
---|---|
get_id() | スレッド識別子を取得 |
yield | コンテキストスイッチを発生させるヒントを提供する。 実装依存の動作。 |
sleep_until(std::chrono::time_point) | 指定した日時までスリープ |
sleep_for(std::chrono::duration) | 指定した時間スリープ |
※ std::this_thread::は省略
以下に使用例を示す。
#include <thread>
#include <chrono>
std::atomic<bool> flag(false);
void f() {
using namespace std::chrono;
std::this_thread::sleep_for(seconds(5)); //OK 5秒間sleep
while(flag == false) {
std::this_thread::yield;
}
std::cout << "f() end." << std::endl;
}
void g() {
system_clock::time_point tp = system_clock::now();
tp += minutes(7);
std::this_thread::sleep_until(tp); //OK 1分後までsleep
flag = true;
std::cout << "g() end." << std::endl;
}
int main() {
std::thread t1(f);
std::thread t2(g);
t1.join();
t2.join();
return 0;
}