2009-08-07 10 views
22

私は非常に単純なスレッドアプリケーションを作成しようとしていますが、boostのスレッドライブラリには新しくありません。私が働いている簡単なテストプログラムは、次のとおりです。(simple)boost thread_group question

#include <iostream> 
#include <boost/thread.hpp> 

int result = 0; 
boost::mutex result_mutex; 

boost::thread_group g; 

void threaded_function(int i) 
{ 
    for(; i < 100000; ++i) {} 

    { 
     boost::mutex::scoped_lock lock(result_mutex); 
     result += i; 
    } 
} 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 

    // launch three threads 
    boost::thread t1(threaded_function, 10); 
    boost::thread t2(threaded_function, 10); 
    boost::thread t3(threaded_function, 10); 

    g.add_thread(&t1); 
    g.add_thread(&t2); 
    g.add_thread(&t3); 

    // wait for them 
    g.join_all(); 

    cout << result << endl; 

    return 0; 
} 

しかし、私はコンパイルして、私は明らかに

$ ./test 
300000 
test: pthread_mutex_lock.c:87: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed. 
Aborted 

の出力を取得し、このプログラムを実行すると、結果は正しいですが、私は心配しています本質的に同じ構造を持つ実際のプログラムがjoin_all()ポイントでスタックしているため、このエラーメッセージについて誰かが私に何が起こっているか説明することができますか?これを行うためのより良い方法がありますか?つまり、いくつかのスレッドを起動し、それらを外部コンテナに格納してから、プログラムを続行する前にすべてのスレッドが完了するのを待ちますか?

ありがとうございました。

答えて

25

私はあなたの問題は、プログラムが終了するときに呼び出されるthread_groupデストラクタによって引き起こされると思います。スレッドグループはスレッドオブジェクトを破壊する責任があります。 boost::thread_groupのドキュメントを参照してください。

メイン関数のスコープ内のローカル変数としてスレッドオブジェクトをスタックに作成しています。したがって、プログラムが終了し、thread_groupがそれらを削除しようとすると、すでに破棄されています。解決策として

新しいとヒープ上に自分のスレッドオブジェクトを作成し、その破壊の世話をthread_groupてみましょう:

boost::thread *t1 = new boost::thread(threaded_function, 10); 
... 
g.add_thread(t1); 
... 
+0

「新しい」メモリ割り当ての省略記号を削除し、thread_groupに渡す必要があります。そうでなければ、途中で何かがうまくいかない(つまりスローする)と、スレッドがリークします。 –

+0

はい、これはそのように思われ、大きなプログラムでもバグの原因となっていました。作業の例では、今使用しています: //は、3つのスレッド g.add_thread(新しいブースト::スレッド(threaded_function、10))を起動します。 g.add_thread(新しいboost :: thread(threaded_function、10)); g.add_thread(新しいboost :: thread(threaded_function、10)); – RandomGuy

+1

あなたがリークしないようにするには、std :: unique_ptr または類似のソリューションを使用し、ptr.get()を使用してgroup_threadにスレッドを提供するのが良いでしょう。 – Klaim

2

add_thread()は、渡したスレッドの所有権を取得します。スレッドグループはスレッドを削除します。この例では、スタックに割り当てられたメモリを削除しています。

メンバ関数 add_thread()

ボイドadd_thread(スレッド*のTHRD)。

前提

式がTHRDを削除するには、整形式 あると 未定義の動作にはなりません。

効果:

は、ブーストの所有権を取得::スレッド オブジェクトはTHRDによって指さし、グループにそれを を追加します。

事後条件

this->サイズ()1つ増加されます。

あなたのコードで何が問題なのか、これが単なるバグの例かどうかは不明です。さもなければコードは正常に見えます

24

あなたがスレッドへのハンドルを必要としない場合は、使用してみてくださいthread_group :: create_thread()ですべてのスレッドを管理する必要性を軽減:

// Snip: Same as previous examples 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 

    // launch three threads 
    for (int i = 0; i < 3; ++i) 
     g.create_thread(boost::bind(threaded_function, 10)); 

    // wait for them 
    g.join_all(); 

    cout << result << endl; 

    return 0; 
} 
+0

create_threadはまだスレッドhttp://www.boost.org/doc/libs/1_39_0/doc/html/thread/thread_management.html#thread.thread_management.threadgroup.create_threadへのハンドルを返します。 add_threadとは異なり、スレッドグループはスレッドを削除する責任を負うことがないため、create_threadを使用することができます。 – shank22

0

それは、上記のいずれも、実際に質問に答えていないに見えます。

私は同様の問題に遭遇しました。この警告の結果(pthread_mutex_lock.c:87:__pthread_mutex_lock:。。アサーション `ミューテックス - > _ データ _owner == 0' は失敗した 中止は)は時々プログラムがスレッドをリークするとboost_resource_error例外が発生するということです。

理由は、ほとんどのスレッドがまだ実行中(終了していない)でも、join_all()の後にプログラムが実行され続けるように見えます。