2014-12-04 2 views
4

내가 따르고있는 튜토리얼에서 작성자는 std::future의 소멸자가 항상 작업을 실행하지 않는다는 것을 보여주는 프로그램을 작성했습니다. 다음 프로그램에서는 std::async()으로 생성 된 10 개의 스레드가 벡터로 이동 한 다음 소멸자가 실행될 때까지 기다립니다. 일부 스레드가 지연되는 이유는 무엇입니까?

#include <iostream> 
#include <future> 
#include <thread> 
#include <chrono> 

int main() 
{ 
    std::cout << "Main thread id: " << std::this_thread::get_id() << std::endl; 

    std::vector<std::future<void>> futures; 
    for (int i = 0; i < 10; ++i) 
    { 
     auto fut = std::async([i] 
     { 
      std::this_thread::sleep_for(std::chrono::seconds(2)); 
      std::cout << std::this_thread::get_id() << " "; 
     }); 
     futures.push_back(std::move(fut)); 
    } 
} 

결과

기계에 의존하지만, 우리가 발견 한 것은 (우리는 메인 스레드 ID를 출력 한 후 인쇄 6 개 ID를 가지고) 소멸자가 실행 된 경우에만 6 스레드가 시작되었다이었다. 이것은 다른 4 개가 지연되고, 지연된 스레드가 std::future의 소멸자 중에 실행되지 않는다는 것을 의미합니다.

제 질문은 일부 스레드가 실행되는 동안 다른 스레드가 지연되는 이유입니다. std::future의 수명이 끝나면 지연시키는 시점은 무엇입니까?

+0

과부하 (코어/물리 스레드의 양이 너무 많은 스레드 만들기)는 모든 작업 전환이 관련되어 시스템 성능을 저하시킬 수 있습니다. – Borgleader

+0

테스트 머신에는 몇 개의 코어/SMT 스레드가 있습니까? – inf

+0

@bamboon 출력 내용이 내 컴퓨터가 아닌 자습서에 표시되었습니다. –

답변

6

동기화로 인해 그 중 일부를 지연시킬 cout의 사용 항상 작업을 실행하지 마십시오.

소멸자 결코이 작업을 실행합니다. 작업이 이미 다른 스레드에서 실행중인 경우 소멸자는 완료 될 때까지 기다리지 만 실행하지는 않습니다. 우리가 발견 한 것은

은 소멸자가

이 잘못을 실행했을 때 단지 6 스레드가 시작되었다이었다, 스레드가 소멸자 실행할 때, 그들은 당신이 std::async를 호출 할 때 시작 (또는되어 시작되지 않습니다 그 이후에는 소멸자가 시작될 때 여전히 실행 중이므로 소멸자가 기다려야합니다.

std :: future의 수명이 끝나는 경우 지연을 지정하는 시점은 무엇입니까?

다시, 소멸자 실행은, 그들이 std::async가 호출 될 때, 그들은 여전히 ​​때 소멸자가 실행을 연기하고, 그래서 그들은 단지 실행되고 않고 멀리 던져, 그리고 소멸자 '아무튼 연기 할 때 그들이 연기되지 않습니다 무엇이든 기다려야합니다.

튜토리얼을 인용하고 있으며 작성자가 혼란 스럽거나 혼란 스럽긴하지만 무슨 일이 일어 났는지에 대한 설명은 오도 된 것입니다.

실행 정책 인수없이 std::async을 호출 할 때마다 C++ 런타임은 새 스레드를 만들지 또는 기능을 연기할지 (이후에 실행할 수 있는지) 여부를 결정합니다. 시스템이 사용 중이면 런타임에서 다른 스레드를 시작하면 시스템 속도가 느려지므로 런타임에서 함수를 지연시킬 수도 있습니다.

+0

그는 다음과 같이 말했습니다 : "다른 작업은 별도의 스레드가 아니라 연속적으로 실행되도록 예약되었습니다. 지연된 작업은 지연된 작업의 경우 소멸자가 작업을 실행하지 않습니다." 그게 정확한 진술인가요? –

+0

네, 정확합니다 ... "소멸자가 작업을 수행하지 않습니다"라고 말한 것입니다 (그리고 당신의 질문에 당신이 표현한 것과 반대입니다!) –

2

귀하의 async() 호출 기능은 (어떤 점에서) 자동으로 정책을 선택 "고 launch::async|launch::deferred 의미는 기본 발사 정책을 사용합니다. 이것은 일반적으로 동시성의 현재 가용성을 최적화 시스템 및 라이브러리 구현에 따라 달라집니다 시스템에서. "

thread::hardware_concurrency은 시스템의 최대 하드웨어 동시성에 대한 힌트를 제공 할 수 있습니다. 이것은 일부 스레드가 반드시 연기되는 이유를 설명하는 데 기여할 수 있습니다 (특히 루프가 하드웨어 동시성보다 강하다면). 그러나 실행중인 다른 프로세스에서도 하드웨어 동시성을 사용할 수 있습니다.

뿐만 아니라 비동기 스레드가 만들어 있습니다 저자는 표준의 소멸자 것으로 나타났다 프로그램 :: 미래를 썼다 (더 here)

+0

좋은 답변입니다. [Coliru 편집기] (http://coliru.stacked-crooked.com/a/8375791eefa5cbf8)에서'thread :: hardware_concurrency()'를 실행하면'1'을 반환합니다. 그러나 10 개의 스레드 중 어느 것도 지연되지 않았습니다. 왜 그런가요? –

+0

앞서 언급했듯이 여기서는 구현 방식이 다릅니다. hardware_cocnurrency는 힌트를 줄지도 모르지만 안타깝게도 그렇게해서는 안됩니다. "이 값의 해석은 시스템 및 구현에 따라 다르며 정확하지 않을 수 있지만 근사치에 불과합니다." – Christophe

+1

@templateboy Jonathan의 응답 상태에 따라 구현이 다릅니다. [그것은 보인다] (http://coliru.stacked-crooked.com/a/932c3d3260bb1891) clang + libC++는 스레드를 시작하는 것을 전혀 지연하지 않습니다. – Praetorian

관련 문제