2017-04-01 80 views
13

我試圖在以前worker_thread開始工作,但可能已結束或不結束時啓動新線程。我已經替換了開始並結束了延時工作。我的代碼是:C++條件變量通知不按預期方式工作

#include <iostream> 
#include <string> 
#include <mutex> 
#include <condition_variable> 
#include <future> 
#include <atomic> 
#include <chrono> 
#include <thread> 

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

void worker_thread() 
{ 
    std::unique_lock<std::mutex> lk(m); 

    static std::atomic<int> count(1); 
    std::this_thread::sleep_for(std::chrono::milliseconds{(count % 5) * 100}); 
    std::cerr << "Start Worker thread: " << count << "\n"; 

    started = true; 
    lk.unlock(); 
    cv.notify_one(); 

    std::this_thread::sleep_for(std::chrono::milliseconds{3000}); 
    std::cerr << "Exit Worker thread: " << count << "\n"; 
    ++count; 
} 

int main() 
{ 
    while(1) { 
     std::async(std::launch::async, worker_thread); 
     std::unique_lock<std::mutex> lk(m); 
     cv.wait(lk, []{return started;}); 
     started = false; 
    } 
} 

輸出看起來像這樣:

Start Worker thread: 1 
Exit Worker thread: 1 
Start Worker thread: 2 
Exit Worker thread: 2 
Start Worker thread: 3 
Exit Worker thread: 3 
Start Worker thread: 4 
Exit Worker thread: 4 
Start Worker thread: 5 
Exit Worker thread: 5 

這不是我想要的行爲。我想要的是像(不完全)這樣的:

Start Worker thread: 1 
Start Worker thread: 2 
Start Worker thread: 3 
Start Worker thread: 4 
Exit Worker thread: 1 
Exit Worker thread: 3 
Exit Worker thread: 4 
Exit Worker thread: 2 
Start Worker thread: 5 
Exit Worker thread: 5 

目前的工作而以前的線程完成下一個線程纔開始。但是,我想在上一個線程中開始工作並且不等待它結束時纔開始下一個線程,只能等待開始。

回答

12

std::async返回一個std::future函數執行的保存結果。就你而言,它是一個被直接摧毀的臨時對象。爲std::future文檔說:

these actions will not block for the shared state to become ready, except that it may block if all of the following are true

✔共享狀態是通過調用創建到std ::異步

✔共享狀態還沒有準備好

✔這是共享狀態的最後一個參考

所有這些都是真實的,所以破壞o f future將阻塞,直到工作器功能將完成執行。

您可以創建分離線程來避免這個問題:

std::thread(worker_thread).detach(); 
+2

還有其他的問題:如果cv.wait正在運行的通知將錯過前cv.notify_one被調用。在提交的代碼中,它很可能會。變量'started'在第一個worker_thread中設置爲true,並保持此狀態。 – CAF

+0

@CAF我忘了寫在while循環結束時開始= false,已經更新了代碼。但我不明白如何解決丟失的通知問題,我不能等待隨機時間,因爲啓動事件可能需要任何時間量。 –

+0

@激光焦點:如果切換std :: async和std :: unique_lock語句在cv.wait之前,等待將在notify_one之前發生。 – CAF