2017-04-01 14 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 ::し

非同期(async)呼び出しによって作成されました✔共有状態への最後の参照でした

これらのすべてが真であり、破壊fはfutureで、ワーカー関数の実行が終了するまでブロックされます。

あなたがこの問題を回避するために切り離されたスレッドを作成することができます。

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

は、他の問題がまだありますcv.notify_oneはcv.wait通知が失われます実行されている前に呼び出された場合。提示されたコードでは、おそらくそうです。変数 'started'は、最初のworker_threadによってtrueに設定され、この状態のままです。 – CAF

+0

@CAF whileループの最後にstarted = falseを書くのを忘れて、コードを更新しました。しかし、私はどのように通知の問題を解決するために理解していない、私は時間の任意の時間を取ることができるので、ランダムな量の時間を待つことはできません.. –

+0

@レーザーフォーカス:std :: asyncとstd :: unique_lockステートメントcv.waitの前に、notify_oneの前に待ち時間が確実に起こります。 – CAF

関連する問題