4

boost::thread の組み合わせ論を学習するために、共通ミューテックス (M) をロックするスレッド用の単純なバリア (BR) を実装しています。ただし、BR.wait() に移動したときに得られる限り、ミューテックスのロックは解放されないため、すべてのスレッドが BR に到達するには、M のロックを手動で解放する必要があります。だから私は次のコードを持っています:

boost::barrier BR(3);
boost::mutex M;

void THfoo(int m){
    cout<<"TH"<<m<<" started and attempts locking M\n";
    boost::lock_guard<boost::mutex> ownlock(M);

    cout<<"TH"<<m<<" locked mutex\n";
    Wait_(15); //simple wait for few milliseconds

    M.unlock(); //probably bad idea
    //boost::lock_guard<boost::mutex> ~ownlock(M);
    // this TH needs to unlock the mutex before going to barrier BR

    cout<<"TH"<<m<<" unlocked mutex\n";
    cout<<"TH"<<m<<" going to BR\n";
    BR.wait();
    cout<<"TH"<<m<<" let loose from BR\n";
}

int main()  
{  
    boost::thread TH1(THfoo,1);
    boost::thread TH2(THfoo,2);
    boost::thread TH3(THfoo,3);

    TH2.join(); //but TH2 might end before TH1, and so destroy BR and M
    cout<<"exiting main TH \n";

    return 0;  
}

M.unlock() は明らかに悪い解決策です (ロックを使用しない)。では、ロックを(単に)解除する方法は?また、すべてのスレッドが終了するまで main() で (適切に) 待機するにはどうすればよいですか? (TH2.join() はまずい。TH2 が最初に終了する可能性があるため...);

私も使用できる条件変数を使用するなど、回避策を提案しないでください。

4

5 に答える 5

8

boost::lock_guardブロックでのスコープに加えて、明示的に 'edboost::unique_lockできる a を使用することもできます。unlock()

boost::unique_lock<boost::mutex> ownlock(M);

cout<<"TH"<<m<<" locked mutex\n";
Wait_(15); //simple wait for few milliseconds

ownlock.unlock();

これは、後で再取得する前にミューテックスを解放する必要がある場合に役立ちます。

join()結合に関しては、すべてのスレッド ハンドルを順番に呼び出すだけです。

于 2012-03-06T10:43:30.947 に答える
4

何かのようなもの:

void THfoo(int m){
  // use a scope here, this means that the lock_guard will be destroyed (and therefore mutex unlocked on exiting this scope
  {
    cout<<"TH"<<m<<" started and attempts locking M\n";
    boost::lock_guard<boost::mutex> ownlock(M);

    cout<<"TH"<<m<<" locked mutex\n";
    Wait_(15); //simple wait for few milliseconds

  }
  // This is outside of the lock
  cout<<"TH"<<m<<" unlocked mutex\n";
  cout<<"TH"<<m<<" going to BR\n";
  BR.wait();
  cout<<"TH"<<m<<" let loose from BR\n";
}

待機については、すべてのスレッドハンドルでjoinを呼び出すだけです(すでに完了している場合、関数はすぐに戻ります)

TH1.join();
TH2.join();
TH3.join();
于 2012-03-06T10:35:47.640 に答える
1

範囲外にしましょう:

void THfoo(int m){
    cout<<"TH"<<m<<" started and attempts locking M\n";
    {
       boost::lock_guard<boost::mutex> ownlock(M);

       cout<<"TH"<<m<<" locked mutex\n";
       Wait_(15); //simple wait for few milliseconds
    }

    // this TH needs to unlock the mutex before going to barrier BR

    cout<<"TH"<<m<<" unlocked mutex\n";
    cout<<"TH"<<m<<" going to BR\n";
    BR.wait();
    cout<<"TH"<<m<<" let loose from BR\n";
}
于 2012-03-06T10:35:27.127 に答える
1
cout<<"TH"<<m<<" started and attempts locking M\n";
{
    boost::lock_guard<boost::mutex> ownlock(M);

    cout<<"TH"<<m<<" locked mutex\n";
    Wait_(15); //simple wait for few milliseconds

} //boost::lock_guard<boost::mutex> ~ownlock(M);
// this TH needs to unlock the mutex before going to barrier BR

cout<<"TH"<<m<<" unlocked mutex\n";

すべてのスレッドである限りjoin、TH2が最初に終了するときの唯一の問題は、TH2が「刈り取られる」前にTH1の実行を終了するjoin必要があり、戻り値などの残りのリソースが解放されることです。3つのスレッドについて心配する価値はありません。そのメモリ使用量が問題である場合は、timed_joinすべてのスレッドを順番に繰り返し試行するために使用できます。

また、不要なことを実行することもできます。メインスレッドに条件変数を待機させ、終了すると各スレッドは終了したことを示す値をどこかに格納し、メインスレッドがjoinそれを実行できるように条件変数に信号を送ります。スレッドが信号を送ることを絶対に確認する必要があります。そうしないと、永遠にそれを待つことになりかねません。したがって、スレッドをキャンセルする場合は注意してください。

于 2012-03-06T10:36:50.653 に答える
1

boost::lock_guard ではなく boost::mutex::scoped_lock を使用する場合、unlock() メソッドがあります。それを呼び出すと、ロックはデストラクタで再ロック解除を試みません。したがって、ロックを独自のブロックに配置するよりも、コードが私の好みに合っていることがわかります。

于 2012-03-06T10:43:09.570 に答える