🐶

C++ std::threadの使い方

2023/11/12に公開

はじめに

C++11から追加されているstd::threadに関する情報について、全てがまとまっているサイトを見つけられなかったため、ここにまとめることにしました。

std::threadのAPI一覧

Unix系のpthreadを比べるととてもシンプルというか何も出来ないthreadという印象です。

API 用途
join スレッド動作完了待ち、スレッドの開放
detach スレッドを生成したプロセスの管理対象から外す (スレッドを生成したプロセスが終了してもdetachされたスレッドはterminateされずに最後まで動き続ける)
get_id スレッド固有のIDを取得
hardware_concurrency H/WでサポートされているCPUスレッド数を取得
joinable コンテキストがスレッドと関連付けられているならtrue、そうでなければfalseを返す
native_handle プラットフォーム依存のスレッドハンドルを取得 (Unix系はpthread_t, WindowsはHANDLEのインスタンスを返す)
swap std::threadをスワップ

基本的な使い方

std::threadのivar (インスタンス変数) 宣言時の第一引数には、スレッド実行するメソッドを指定し、第二引数以降にはスレッド実行対象のメソッドの引数を指定します (メソッドに引数がなければ何も指定しない) 。

std::threadはivarを生成した時点でスレッド動作開始し、join()メソッドでそのスレッドが終了するまでそのコンテキスト (以下のサンプルプログラムだとmain関数のプロセス) が待ちに入り、スレッド動作後にスレッドコンテキストの開放を行います。スレッド生成および動作後には、必ず生成したコンテキストでjoin()をコールすることを忘れないようにして下さい。通常のプログラミングでは基本的にdetachを利用することはないと思います。

よく忘れがちですが、コンパイル時には-pthreadオプションをお忘れなく。

#include <iostream>
#include <thread>

void ThreadFunc(int num) {
  std::cout << "ThreadFunc " << num << std::endl;
}

int main() {
  std::thread th1(ThreadFunc, 1);
  th1.join();

  auto func = [](std::string message) {
    std::cout << "thread id = " << std::this_thread::get_id()
	      << " " << message << std::endl;
  };
  std::thread th2(func, "Hellow, World!");
  std::cout << "th2's id = " << th2.get_id() << std::endl;

  return 0;
}
実行結果
ThreadFunc 1
th2's id = 0x700009cef000
thread id = 0x700009cef000 Hellow, World!

Tips

スレッドの優先度設定

std::threadではスレッドに対する詳細設定が出来ませんので、native_handle()でプラットフォーム固有のスレッドハンドラを取得し、そのプラットフォームに合わせた形で設定する必要があります。ここではUnix系 (Linux, macOS) の例を以下に示します。

int main() {
  auto func = [](std::string message) {
    std::cout << "thread id = " << std::this_thread::get_id()
              << " " << message << std::endl;
  };
  std::thread th2(func, "Hellow, World!");

  // 優先度を設定
  struct sched_param param;
  param.sched_priority = 0;
  if (pthread_setschedparam(th2.native_handle(), SCHED_OTHER, &param) != 0)
    std::cout << "Priority set Error" << std::endl;

  th2.join();

  return 0;
}

pthread_setschedparamについての参考文献

H/WでサポートされているCPUスレッド数を調べる

int main() {
  std::cout << "concurrency = " << std::thread::hardware_concurrency()
            << std::endl;
  return 0;
}
実行結果
concurrency = 6

Discussion