2013-06-03 10 views
22

別のスレッドがタスクキュー(ロングストーリー)の処理を完了するまで、条件変数を使用してスレッドを停止しています。だから、1つのスレッドで私がロックし、待って次のようにブースト条件変数を使用してスレッドが処理を完了するまで待機するにはどうすればよいですか?

boost::mutex::scoped_lock lock(m_mutex); 
m_condition.wait(lock); 

を他のスレッドには、それのタスクを完了すると、それは待機中のスレッドを知らせる:

boost::mutex::scoped_lock lock(m_parent.m_mutex); 
m_parent.m_condition.notify_one(); 

私は見ています問題は、待機ということです私はそれに続く命令(私はxcode、fyiを使用しています)にブレークポイントを設定しない限り、スレッドは待機を停止しません。はい、これは奇妙に思えます。なぜこれが起こっているのか誰にも分かりますか?私は条件変数を誤って使用していますか?

+0

コードは...少し混乱して第二 '' m_parent.m_mutex'同じインスタンスをm_mutex'ですか? –

答えて

42

はい、条件変数を誤って使用しています。 「条件変数」は、実際にはシグナル伝達メカニズムに過ぎません。また、条件をテストする必要があります。場合によっては、wait()を呼び出すスレッドが開始される前に、notify_one()を呼び出すスレッドが実際に完了することがあります。 (または少なくともnotify_one()コールがwait()コールの前に発生しています)。これは「失敗したウェークアップ」と呼ばれています。 worker_is_done==true場合は、他のスレッドでも、あなたがちょうど落ちるよ待って開始する前に

bool worker_is_done=false; 

boost::mutex::scoped_lock lock(m_mutex); 
while (!worker_is_done) m_condition.wait(lock); 

boost::mutex::scoped_lock lock(m_mutex); 
worker_is_done = true; 
m_condition.notify_one(); 

ソリューションは、実際にあなたが気に条件が含まれている変数を持つことですwhileループを介して右にwait()と呼ぶことなく、

このパターンは非常に一般的なので、whileループをラップしていないと、あなたは常にバグがあると言っています。実際には、ときC++ 11はブーストに似たものを採用した::述語ラムダ式をとること)は、待機(新しい種類を追加condtion_variable(基本的にそれはあなたのためにwhileループし):

std::condition_variable cv; 
std::mutex m; 
bool worker_is_done=false; 


std::unique_lock<std::mutex> lk(m); 
cv.wait(lk, []{return worker_is_done;}); 
+0

待機スレッドに必要な 'boost :: mutex :: scoped_lock lock(m_mutex);'とは何ですか? notify_one()はargsをとらない。 – ItsmeJulian

+0

'worker_is_done'にアトミックな書き込みを提供するためにあります。代わりに 'bool'ではなく' atomic 'とタイプを宣言することです。 –

+0

@DavidStone 1バイトの割り当てがアトミックなプロセッサ上でコードを実行している場合はどうでしょうか? x86?その場合はロックは必要ありませんか? – user3286661

2

は、私は、議論に基づいて、ブースト条件を使用する方法を示す例を実装しました。

#include <iostream> 

#include <boost/asio.hpp> 
#include <boost/thread/mutex.hpp> 
#include <boost/thread/thread.hpp> 

boost::mutex io_mutex; 
bool worker_is_done = false; 
boost::condition_variable condition; 

void workFunction() 
{ 
    std::cout << "Waiting a little..." << std::endl; 
    boost::this_thread::sleep(boost::posix_time::seconds(1)); 
    worker_is_done = true; 
    std::cout << "Notifying condition..." << std::endl; 
    condition.notify_one(); 
    std::cout << "Waiting a little more..." << std::endl; 
    boost::this_thread::sleep(boost::posix_time::seconds(1)); 
} 

int main() 
{ 
    boost::mutex::scoped_lock lock(io_mutex); 
    boost::thread workThread(&workFunction); 

    while (!worker_is_done) condition.wait(lock); 
    std::cout << "Condition notified." << std::endl; 
    workThread.join(); 
    std::cout << "Thread finished." << std::endl; 

    return 0; 
} 

Boost condition variable example

+3

worker_is_doneをtrueに設定する前にworkFunctionでロックを取るべきではありませんか? –

+0

私は彼がすべきだと思います。 –

関連する問題