1

我有一個「引擎」異步處理任務和一項任務,我想等到該任務處理。併發上的boost :: condition_variable :: notify_one()

boost::condition_variable cvWorkDone; 

DoSomeWork() 
{ 
    PostAsyncJob(DoWorkAsync) // is a boost::asio::post 

    boost::mutex::scoped_lock lock(mtxWorkDoneCv); 
    cvWorkDone.wait(lock); 
} 


DoWorkAsync() 
{ 
    // do some work ... 

    cvWorkDone.notify_one(); 
} 

問題是上面的代碼有競爭條件。如果DoWorkAsync()DoSomeWork()等待之前通知boost::condition_variable

我看到boost::condition_variable::wait有第二個參數,可以用來實現這樣的事情

bool bWait; 

DoSomeWork() 
{ 
    bWait = true; 
    PostAsyncJob(DoWorkAsync) // boost::asio::post 

    boost::mutex::scoped_lock lock(mtxWorkDoneCv); 
    cvWorkDone.wait(lock, bWait); 
} 


DoWorkAsync() 
{ 
    // do some work ... 
    boost::mutex::scoped_lock lock(mtxWorkDoneCv); 
    cvWorkDone.notify_one();  
    bWait = false; 
} 

一個布爾值,但併發還是有的...我該如何解決?

回答

3

由於條件變量不維護他們是否已經暗示與否的狀態,你需要保持狀態的任何可能的條件變量單獨信號(在某些情況下,如隊列的原因,發送條件變量的原因可以異步消失)。所以你可能在你的代碼是這樣的:

boost::condition_variable cvWorkDone; 
bool workdone = false; 

DoSomeWork() 
{ 
    PostAsyncJob(DoWorkAsync) // is a boost::asio::post 

    boost::mutex::scoped_lock lock(mtxWorkDoneCv); 
    while (!workdone) { 
     cvWorkDone.wait(lock); 
    } 
} 


DoWorkAsync() 
{ 
    // do some work ... 

    { 
     boost::mutex::scoped_lock lock(mtxWorkDoneCv); 
     workdone = true; 
    } 
    cvWorkDone.notify_one(); 
} 

注意,這也可以避免boost::condition_variable::wait()虛假的回報。從升壓文檔上boost::condition_variable::wait()

時通過調用通知這個 - > notify_one()或這個 - > notify_all(),或不合邏輯的線程將解除封鎖。

+0

這是爲什麼解決併發問題? 'workdone = true;'和'cvWorkDone.notify_one();'可以在'!workdone'和'vWorkDone.wait(lock);'之前執行。主線程將等待一個永遠不會到來的notify_one。 – cprogrammer

+0

當調用this-> notify_one()或this-> notify_all(),**或虛假**時,線程將被解除阻塞。聽起來不太好。 – cprogrammer

+0

這解決了併發問題,因爲只有在持有互斥鎖的情況下才更新和檢查「workdone」。當且僅當'DoAsyncWork()'尚未到達'workdone = true'語句時,服務員才能進入'cvWorkDone.wait(lock)'語句。相反,如果'DoWorkAsync()''套= workdone的TRUE'服務員到達之前'而(!workdone)',那麼服務員會注意到'workdone'已定,並不會打擾條件變量的等待。要重申的是,這裏沒有比賽,因爲線程必須獲取互斥鎖才能設置或檢查「workdone」。 –

相關問題