2012-03-08 81 views
2

私はユーザー提供の関数を実行するためのpthreadを作成するC++アプリケーションを持っています。私はスレッドを終了するときに何らかの方法で警告を出して、スレッドを維持するために使用しているpthreadの配列からそのスレッドを削除できるようにしたいと考えています。これを行う方法はありますか、関数がちょうど "魔法の価値"を設定するべきかどうかです。 pthreadsを生成する私のメインコードは一種のrunloopにあるため、終了条件を簡単にチェックできます。pthreadが終了したときに関数を実行する


また、過負荷私のスレッドを追跡するために、無理std::vector<pthread_t>を使用していますか?スレッドの数は必ずしも一定の定数ではなく、多くのスレッドまたは非常に少数のスレッドしか実行できません。または、これらの追加と削除に便利なもう1つのSTLコンテナがあります(常に片側に追加され、ほとんどどこでも削除されます)。 pthreadsを追跡するための他の構造がありますか?スタックやリストはここにありますか?寛大な最大の良い標準C配列ですか?問題の性質上、実行する必要があるユーザー関数を渡すワーカースレッドの固定サイズの配列を維持することもできます。これは良い解決策ですか?

ご迷惑をおかけして申し訳ありませんが、私はこれが問題になることのないような動的言語のスレッドでのみ作業しています。


EDIT(3/08/12): jojojapanの答え@読んだ後、私は一種のスレッドプールを使用することを決定しました。私の構造では、1つのプロデューサ(1つのスレッド)と多くのコンシューマ(プール内のワーカースレッド)があります。マルチスレッドの1つのプロデューサを多く消費するために作られたデータ構造はありますか?または、std::queuepthread_mutex_tを使用してもよろしいですか?あなたが考慮する必要があります

+0

「ユーザー提供機能を実行する」と言うと、スレッドfuncを書くのはあなたですか? – Duck

+0

動的言語?あなたはGC言語を意味します;)。 –

+0

@Duck:いいえ。私はライブラリを書いています。それを使用するプログラマは、これらの関数を書き込みます。 – Linuxios

答えて

3
  1. 1つのオプションは、実際には終了し、削除スレッドを、彼らは仕事を終えたら、代わりに生きそれらを維持し、それらが彼らに割り当てる新しいタスクを待つ必要はありませにあります。あなたは二つのことをすることによって、これを達成することができ

    1. は、同時キューまたはそれらを別のスレッドによって与えられる信号を待ちますいくつかの他の技術を使用し
    2. スレッドで(ほぼ)無限ループを使用します。デザインパターンと戦略については、いくつかのSOの質問(例: this one
  2. あなたは本当ににしたい場合は、スレッドが終了したら、あなたはpthread_cond_tを使用すると、スレッドがそのreturn声明に達する直前に、それにpthread_cond_signalを呼び出すことができ、信号を送ります。もちろん、これらのシグナルを待っている他のスレッドが実行されており、対応するスレッドをベクターから削除することによってそれらに作用します。使用法の詳細は、対応するマニュアルページに記載されていますが、this SO postにも記載されています。スレッドで最も使用されたリソースに依存します。ワーカースレッドの数について

    1. :コメントや質問の編集した部分に関連する

    編集。これらのスレッドが主に行うのは計算とメモリアクセスのビットであり、言い換えればCPUにバインドされている場合は、CPUが維持できるスレッド数を使用することが理にかなっています(具体的には、あなたのCPUがお互いに遅くなる前に実行できるコアあたりの(ハードウェア)スレッドの数。あなたが作成しているスレッド(ソフトウェアスレッド)は、スレッド数と同じかそれ以上でなければなりません。ハードウェアスレッドはwhat @Tudor says hereに従って合理的です))。しかし、スレッドがメモリ(メモリバウンド)またはハードディスク(IOバウンド)やネットワーク、NFS、その他のサーバなどの他のリソースを大量に使用する場合は、スレッドの数を減らすことができます)、(b)特定のリソースに不当に多くの負荷をかけることはない。適切な数のスレッドを決定することは実験の問題かもしれませんし、数を設定可能に保つことは一般的には良い考えです。

  3. 作業タスクを保存するための最良のデータ構造について:私が先に引用した投稿のコメントに記載されているconcurrent bounded queueはおそらく非常に良いでしょう。私はそれを自分で試していない。しかし、信号を単純にしたい場合は、signal/mutex技法を使って適切に保護しておけば、標準std::queue、あるいは単にstd::vectorでさえ悪い選択ではありません。

+0

答えをありがとう。あなたの最初の選択肢は、多くの意味があります。ちょうど2つのことがあります:1つは、ワーカースレッドがいくつあると思いますか、2つは、実行する必要のあるコールを格納するためにどのデータ構造を使用すべきですか? ( 'pthread_mutex_t'でロックされた' std :: queue'、または特別なスレッディングキュークラス)。また、私はこれを質問に入れます。プロデューサーと消費者はそれぞれ1人です。 – Linuxios

1

戦略全体を変更し、既存のスレッドプールライブラリを使用することを検討してください。彼らはあなたのために仕事をします、あなたは非常に面白いデバッグではありませんたくさん保存します。

Boost.threadプールは、多くのうちの1つで、linkです。

1

これを行う簡単な方法は、パイプを使用することです。

スレッドを生成する前にパイプを開きます。あなたのスレッドデータの一部としてパイプfdを渡します。スレッドが終了する前に、パイプにpthread_self()を書き込みます。パイプのリード側にメインスレッドまたは別のスレッドを持ってください。デッドスレッドのtidを読み込み、すぐにpthread_joinを実行します。 (別のリーパースレッドの場合は、パイプの読み込みをブロックすることができ、メインにある場合は選択/ポーリングなどの一部にするだけです)

これにより、データ構造を使用しない柔軟性が得られます必要がない場合は、TIDをすべて保存してください。あなたがそれらを保存したい場合、リストやマップはベクトルよりも良い選択です。

スレッドをメインに起動し、それらを収集する別の「リーパー」スレッドがあり、それらをいくつかの構造体に保存したい場合は、その2つの構造体の間で構造体へのアクセスを同期させる必要があります。

+0

パイプは、同じプロセスの2つのスレッド間でTIDを渡すために使用するかなり重いツールのようです。代わりに、完了したTIDとpthread_cond_signalの共有リストを使用して、新しいTIDがリストに追加されたことを通知します。 –

+1

パイプは特に重い重量ではなく、この場合、パイプはN個のスレッドで償却されます。同期はPIPE_BUFサイズのデータ​​で自動的に行われます。パイプのコピーをわずかに犠牲にして、比較的使い易いものになります。 – Duck