2017-04-01 10 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을 반환합니다. 귀하의 경우, 그것은 일시적으로 파괴되는 immendatly 개체입니다. 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 ::

비동기 호출에 의해 만들어진 ✔ 공유 상태에 대한 마지막 참조입니다.

모든 것이 사실이므로 파괴 작업자 함수가 실행을 완료 할 때까지 future이 차단됩니다.

당신은이 문제를 피하기 위해 분리 된 스레드를 만들 수 있습니다

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

여전히 다른 문제가 있습니다 cv.wait 알림이 누락 될 실행되기 전에 cv.notify_one가 호출됩니다. 제시된 코드에서 아마 가능할 것입니다. 변수 'started'는 첫 번째 worker_thread에 의해 true로 설정되고이 상태로 유지됩니다. – CAF

+0

@CAF while 루프가 끝날 때 시작된 = false를 작성하는 것을 잊어 버렸습니다. 코드를 업데이트했습니다. 그러나 나는 누락 된 통지 문제를 해결하는 방법을 이해하지 못한다. 시작 이벤트가 어떤 시간도 걸릴 수 있기 때문에 무작위로 기다릴 수는 없다. –

+0

@Laser Focus : 당신이 std :: async와 std :: unique_lock 문을 전환하면 cv.wait 전에, notify_one 전에 대기가 확실히 일어난다. – CAF