web-dev-qa-db-ja.com

(単純な)boostthread_groupの質問

かなり単純なスレッドアプリケーションを作成しようとしていますが、boostのスレッドライブラリは初めてです。私が取り組んでいる簡単なテストプログラムは次のとおりです。

#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()ポイントでスタックしているため、このエラーメッセージが心配です。誰かが私に何が起こっているのか説明できますか?これを行うためのより良い方法はありますか?つまり、いくつかのスレッドを起動し、それらを外部コンテナーに格納し、プログラムを続行する前にすべてが完了するのを待ちますか?

ご協力いただきありがとうございます。

24
RandomGuy

問題の原因は、プログラムの終了時に呼び出されるthread_groupデストラクタだと思います。スレッドグループは、スレッドオブジェクトを破棄する責任を負います。 boost :: thread_group ドキュメントも参照してください。

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

解決策として、newを使用してヒープ上にスレッドオブジェクトを作成し、thread_groupにそれらの破棄を処理させます。

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

スレッドへのハンドルが必要ない場合は、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;
}
27
Andy

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

メンバー関数 add_thread()

void add_thread(thread * thrd);

前提条件

Delete thrdという式は整形式であり、未定義の動作にはなりません。

効果:

Thrdが指すboost :: threadオブジェクトの所有権を取得し、それをグループに追加します。

事後条件

this-> size()が1つ増えます。

それがあなたのコードの何が悪いのか、それともこれが単なるバグの例なのかわからない。それ以外の場合、コードは正常に見えます。

3
Eugene

上記のどれも実際に質問に答えていないようです。

私は同様の問題に遭遇しました。この警告の結果(pthread_mutex_lock.c:87:__ pthread_mutex_lock:アサーション `mutex-> _data。 _ owner ==0'failed。Aborted)は時々プログラムですスレッドがリークし、boost_resource_error例外が発生します。

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

1
Sean