2013-06-03 49 views
22

我正在使用條件變量來停止線程,直到另一個線程完成處理它的任務隊列(長篇故事)。因此,在一個線程我鎖和等待:如何使用boost條件變量來等待線程完成處理?

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_mutex'相同的實例作爲第二個'm_parent.m_mutex'? –

回答

42

是的,你濫用條件變量。 「條件變量」實際上只是信號機制。你還需要測試一個條件。在你的情況下,可能發生的事情是,調用notify_one()的線程實際上在調用wait()的線程開始之前完成。 (或者至少,notify_one()呼叫在wait()呼叫之前發生。)這被稱爲「錯過喚醒」。

的解決方案是真正有一個包含你所關心的條件變量:

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(); 

如果worker_is_done==true其他線程甚至開始然後就等着之前你只下跌直接通過while循環而無需調用wait()

這種模式很常見,我甚至可以說如果你沒有while循環包裝你的condition_variable.wait(),那麼你總是有一個錯誤。事實上,當C++ 11採用了類似於升壓的東西::接受一個謂詞lambda表達式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()不需要參數。 – ItsmeJulian

+0

它提供了一個原子寫入'worker_is_done'。另一種方法是將類型聲明爲「原子」而不是「bool」。 –

+0

@DavidStone如果我們在一個處理器上運行代碼,其中1字節的賦值是基本的,例如。 86?在這種情況下我們不需要鎖,是嗎? – 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

我認爲他應該。 –