boost::threadにまつわる思う色々

半分メモ変わり。Boost::threadには大きく分けて二通りのThread生成方法がある。

  1. staticな関数で構成された、0からスタートのスタティックスレッド
  2. あるインスタンスがバインドされて実行されるインスタンスベーススレッド

今仮に名前を「スタティックスレッド」と「インスタンスベーススレッド」とした。

ここは大きな違いがあって、おそらくスタティックスレッドは「最後にdetouch()が正しい」と思う。スタティックスレッドは『基本的に』Conditionや、Mutexで同期をとることができない。確かに方法はある。例えば、global変数としてそれら(Condition、Mutex)を作る。または、あるクラスにstatic変数として宣言する。しかし、まずglobal変数は、作るべきではない。次に、クラス変数で、static変数として宣言する。これは一見良さそうだが、単にglobal変数を囲っただけと同じ。特にクラス内メソッドと協調できない。ならばstaticをつけない場合は、となるが、その場合は、クラスのインスタンスが破棄された時点でそれらMutexも破棄されてしまい、動き続けるスレッド側がそれを参照できなくなる。

なので、できるかどうかというより、スタティックスレッドは「detuoch()で終了可能な設計」にするのが正しいと思う。

ただしこれはタスクレベル並列化の話しで、データレベル並列化では通用しない。

タスクレベルとは、「このスレッドは音を再生しよう」とか「このスレッドはファイルに書き込みしよう」というように、役割が決まったスレッドのこと。なので、同じクラスのスレッドはできにくい(音を出すスレッドが1000個あってもあまり意味がない)。データレベル並列化とは、まさしくデータレベルの並列化。ある関数を適用しなければならないデータの入ったVectorが1万個あったら、それを分割して並列化するような感じ。この場合は同じようなスレッドが並列数に応じて生成される。

このデータレベル並列化の場合は、「最終的にはjoin_all()」される「スタティックなスレッド」が使われるべきだろう。理由は、データのコピーさえできればいいこと、同期処理が特に必要ないこと、最終的にはメインプロセスで、結果の集計が必要なこと。

なので、

  1. スタティックスレッド
    1. データ並列ならnon detouch
    2. タスク並列ならdetouch

だ。


今までスタティックスレッドについて書いたけれど、逆に、インスタンスベーススレッドだとどうなるのかということ。これは「MUST join()」ということになる。理由はインスタンスのデストラクタが呼ばれたときにどうするのかということが常につきまとうからだ。