1
#include <iostream>
#include <boost/thread.hpp>
using std::endl; using std::cout;
using namespace boost;


mutex running_mutex;

struct dostuff
{
    volatile bool running;
    dostuff() : running(true) {}
    void operator()(int x)
    {
        cout << "dostuff beginning " << x << endl;
        this_thread::sleep(posix_time::seconds(2));
        cout << "dostuff is done doing stuff" << endl;
        mutex::scoped_lock running_lock(running_mutex);
        running = false;
    }
};

bool is_running(dostuff& doer)
{
    mutex::scoped_lock running_lock(running_mutex);
    return doer.running;
}

int main()
{
    cout << "Begin.." << endl;
    dostuff doer;
    thread t(doer, 4);

    if (is_running(doer)) cout << "Cool, it's running.\n";

    this_thread::sleep(posix_time::seconds(3));

    if (!is_running(doer)) cout << "Cool, it's done now.\n";
    else cout << "still running? why\n"; // This happens! :(

    return 0;
}

上記のプログラムの出力はなぜですか?

始めて..
かっこいい、走っている。
4つのdostuffを開始
するdostuffは、
まだ実行中のものを実行して実行されますか?どうして

それが行われたときに、どうすればdostuffは正しくフラグを立てることができますか?私はそれを待っているのではなく、それが終わったときに通知を受けたいだけです。

4

4 に答える 4

4

この例の問題は、のインスタンスが2つあるdostuffため、でfalseに設定されているバージョンがoperator()メインのバージョンとは異なることです。

スレッド管理ドキュメントから:

新しいスレッドは、パラメーターなしで呼び出すことができる呼び出し可能なタイプのオブジェクトをコンストラクターに渡すことによって起動されます。次に、オブジェクトは内部ストレージにコピーされ、新しく作成された実行スレッドで呼び出されます。オブジェクトをコピーしてはならない(またはコピーできない)場合は、boost::refを使用して関数オブジェクトへの参照を渡すことができます。この場合、Boost.Threadのユーザーは、参照先のオブジェクトが新しく作成された実行スレッドよりも長生きすることを確認する必要があります。

オブジェクトをコピーしたくない場合は、次を使用しますboost::ref

thread t(boost::ref(doer), 4);
于 2010-05-28T00:30:20.927 に答える
2

寝るだけでスレッドが終了するとは限りません。

スレッドでjoinを呼び出すことができます。これは、スレッドが完了するまで待機してから、フローを再開します。

発生している特定のイベントをスレッド間で高度に通知するには、ブースト条件を使用できます。

于 2010-05-28T00:10:36.467 に答える
1

あなたの問題は実際にはあなたのコードのバグだと思います。Boostのドキュメントからthread

引数付きのスレッドコンストラクタ

テンプレート<classF、class A1、class A2、...>
thread(F f、A1 a1、A2 a2、...);

前提条件:
Fおよび各A nは、コピー可能または移動可能である必要があります。

効果:
まるでthread(boost :: bind(f、a1、a2、...))のように。その結果、fと各a nは、新しいスレッドによるアクセスのために内部ストレージにコピーされます。

したがって、スレッドは、実行可能な状態をチェックしているオブジェクトではなく、doerの独自のコピーを変更していると思います。

于 2010-05-28T00:27:52.477 に答える
0

本当の問題は、dostuffスレッドがシグナルを送信する方法ではなく、メインスレッドがシグナルを受信する方法です。私のお気に入りの方法は、socketpair()を使用してローカルソケット接続を作成し、一方のソケットを子スレッドに、もう一方のソケットをメインスレッドに割り当てることです。次に、2つのスレッドはソケット接続を使用して相互に通信できます。あなたの場合、必要なのは、子スレッドが終了する直前にソケットでバイトを送信する(またはソケットファイル記述子を閉じる)ことだけです。これで、メインスレッドをselect()またはpoll()またはそれがブロックしているものは何でも、子スレッドがタスクを終了したことを通知します。

メインスレッドは、リソースを解放する前に、子スレッドが本当に死んでいることを確認するために、子スレッドのスレッドIDでjoin()を呼び出す必要があることに注意してください...そうしないと、子スレッドがシグナルを送信した後、スレッドのクリーンアップルーチンが完了する前に、メインスレッドがリソースを解放するという競合状態が発生する可能性があります。

于 2010-05-28T00:16:11.103 に答える