アプリケーション開発ポータルサイト
ServerNote.NET
Amazon.co.jpでPC関連商品タイムセール開催中!
カテゴリー【C/C++
【C++】カラのstd::threadを生成し条件を満たした時だけ実体化しスレッド実行
POSTED BY
2023-12-05

std::threadはコンストラクタと同時にスレッドを実行するので、ある条件を満たした時だけ実行するものとそうでないものを統一管理しようとするならば、

#include <thread>

int i = 1;

if(i == 1){
   std::thread t1(func);
}

if(i == 2){
   std::thread t2(func);
}

t1.join();
t2.join();

などと書きたいところだが、当たり前ながらif内で生成したt1,t2にその外からjoinできるはずが無くコンパイルエラーとなる。このようなことをしたい場合sharedポインタとして定義すれば可能となる。以下のように書けばよい。

#include <thread>
#include <memory>

int i = 1;
std::shared_ptr<std::thread> t1 = std::shared_ptr<std::thread>();
std::shared_ptr<std::thread> t2 = std::shared_ptr<std::thread>();

if(i == 1){
   t1 = std::make_shared<std::thread>(func);
}

if(i == 2){
   t2 = std::make_shared<std::thread>(func);
}

if(t1.get() != nullptr){
   t1->join();
}

if(t2.get() != nullptr){
   t2->join();
}

make_sharedされた実体があるのなら(get()がnullptrでないなら)、ポインタアクセス演算子でjoinする。

その他、std::threadの基本的な使い方メモとしてのテンプレソースを以下に示す。

C/C++std_thread.cppGitHub Source
#include <iostream>
#include <string>
#include <memory>
#include <thread>
#include <mutex>

std::mutex gMutex;

class Test {
public:
  Test(void) {}
  ~Test(void) {}
  void Thread_Make(void);
  void Thread_Func(int &i, std::string &s);
};

void Test::Thread_Make(void) {

  std::shared_ptr<std::thread> t1 = std::shared_ptr<std::thread>();
  std::shared_ptr<std::thread> t2 = std::shared_ptr<std::thread>();

  int i1 = 5, i2 = 10;
  std::string s1 = std::string("もじ1");
  std::string s2 = std::string("もじ2");

  if(i1 > 0){
    t1 = std::make_shared<std::thread>(&Test::Thread_Func, this, std::ref(i1), std::ref(s1));
  }

  if(i2 > 0){
    t2 = std::make_shared<std::thread>(&Test::Thread_Func, this, std::ref(i2), std::ref(s2));
  }

  if(t1.get() != nullptr){
    t1->join();
  }

  if(t2.get() != nullptr){
    t2->join();
  }
}

void Test::Thread_Func(int &i, std::string &s) {

  gMutex.lock();

  std::cout << "thread id = " << std::this_thread::get_id() << ", i = " << i << ", s = " << s << std::endl;

  gMutex.unlock();
}

int main(void) {

  Test test = Test();
  test.Thread_Make();

  return 0;
}

ポイントは以下。

・ミューテックスはクラスのメンバ変数として宣言できない。グローバルな箇所で宣言する。
・スレッド実行関数に変数の参照を渡したい場合std::refで囲う
・現在実行されているスレッドのIDを取得するにはstd::this_thread::get_idを使う。
・関数自体をミューテックスで排他制御する場合関数入り口でstd::lock_guard<:mutex> guard(gMutext);とすればunlockは不要となる。

コンパイル、実行結果

g++ std_thread.cpp -pthread

./a.out

thread id = 140387569567488, i = 5, s = もじ1
thread id = 140387561174784, i = 10, s = もじ2

なお、mutexでlock排他制御しなかった場合coutの出力は以下のように不規則出力になってしまう。

thread id = thread id = 140287169480448, i = 140287177873152, i = 510, s = , s = もじ1もじ2
※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!
ご連絡は以下アドレスまでお願いします★

☆ServerNote.NETショッピング↓
ShoppingNote / Amazon.co.jp
☆お仲間ブログ↓
一人社長の不動産業務日誌
【キーワード検索】