2014-01-24 1 views
7

조인 가능한 std::thread이 소멸자에서 thread::join()을 실행할 가능성이있는 경우 가끔 유용합니다. 아래 예제를 참조하십시오.joinable std :: thread가 자동으로 결합되지 않는 이유는 무엇입니까?

예 1 (오류) : 예외가 발생한 후에 객체 std::thread이 파괴되었습니다. 일단 흐름이 범위를 벗어나면 결합자가 일어나기 전에 소멸자가 호출됩니다. STL은 '중단'이라는 오류 메시지를 표시합니다.

int main(int argc, const char * argv[]) 
{ 
    try 
    { 
     thread t([]() 
     { 
      this_thread::sleep_for(chrono::seconds(1)); 
      cout << "thread done" << endl; 
     }); 

     throw exception("some exception"); 

     t.join(); 
    } 
    catch (const exception &) 
    { 
     cout << "exception caught!" << endl; 
    } 

    cout << "main done" << endl; 

    return 0; 
} 

예 2 (올바른 방법) : 개체 t()가 모두 시도하고 캐치 블록에 넣어 내 시도-catch 블록 이전에 생성하고 가입되어 . 그래서 join()이 일어난다.

int main(int argc, const char * argv[]) 
{ 
    thread t; 

    try 
    { 
     t = thread([]() 
     { 
      this_thread::sleep_for(chrono::seconds(1)); 
      cout << "thread done" << endl; 
     }); 

     throw exception("some exception"); 

     t.join(); 
    } 
    catch (const exception &) 
    { 
     t.join(); 
     cout << "exception caught!" << endl; 
    } 

    cout << "main done" << endl; 

    return 0; 
} 

... 그리고 질문 : 가 소멸자에 자동으로 참여하지 않는 조인 std::thread 이유는 무엇입니까?

자동으로 발생하면 훨씬 쉬울 것입니다. 예를 들어 try-catch 블록 내부에서 스레드를 사용할 때는 조심해야합니다. 그러나 누군가가 이런 식으로 설계했을 때 생각했습니다. std::thread 이렇게하면됩니다. 그래서 이유가 있어야합니다 ... 그 이유는 무엇입니까?

PS : 나는 우리가 수업 시간에 std::thread을 envolve하고 ...이 새로운 클래스의 소멸자에 join()를 넣을 수 있습니다 알고 그래서 자동된다. 그러나 이것은 중요한 것이 아닙니다. 제 질문은 실제로 std::thread 그 자체에 관한 것입니다.

+0

우려 사항을 분리합니다. 쓰래드를 시작하고 파괴가 완료 될 때까지 기다리는 것을 원하면 쓰십시오. –

+1

위 코드가'join()'이 일어나는 것을 보장하지 않는다는 것에주의하십시오. C++에서는 어떤 유형의 값도 던질 수 있습니다. 즉,'std :: exception'에서 파생 될 필요는 없습니다. C++에서 예외가 발생했는지 여부와 관계없이 일부 동작이 발생하도록 보장해야하는 경우 소멸자에서 정리가 발생하는 RAII 핸들을 사용하십시오. – zmb

+0

이것에 관해서는 알았습니다. std :: exception 만 던지는 것으로 가정했습니다. 그러나 나는 당신이 의미하는 것을 이해합니다. –

답변

14

이유는 간단하기 때문에 당신은 그것에 대해 생각하게됩니다. 범위를 이스케이프하는 예외로 인해 std::thread 객체가 파괴 된 경우 조인은 스택 unwinding 중에 차단 대기를 유발할 수 있습니다. 이는 종종 바람직하지 않으며, 대기중인 스레드가 차례대로 대기 중일 경우 교착 상태가 발생할 수 있습니다 대기중인 스레드의 부분.

이 상황에서 응용 프로그램을 종료하게되면 프로그래머는 객체가 손상 될 수있는 조건에 대해 적극적으로 생각하고 스레드가 올바르게 결합되도록해야합니다.

+1

예 - 시스템 종료가 실패 할 때 완벽한 레시피를 보내는 것처럼 들립니다. –

관련 문제