2014-12-15 2 views
25

루프 중에 새로운 스레드를 만드는 것이 안전합니까? 나는이 방법을 시도했다 :루프에 새 스레드를 만드는 것이 안전합니까?

std::thread thread(ClientLoop,clientSocket) 

하지만 함수가 반환하면 바로 오류가 발생합니다.

while (true){ 
    cout << "Waiting for new connections" << endl; 
    clientSocket = accept(listenSocket, nullptr, nullptr); 
    cout << "Client connected" << endl; 
    new thread(ClientLoop,clientSocket);     
} 

이렇게하면 작동하지만, 메모리 누수가 없는지 궁금합니다. 감사.

+5

: 당신이 정말로 이렇게 할 경우

, 그것은 이런 식으로 끝났다? 이것은 너무 많은 연결을 받아들이는 무한 루프이기 때문에 스택 오버플로가 될 수 있습니까? – Codor

+0

그것은 R6010을 던졌습니다 - abort()가 호출되었습니다 – Tomas

+0

새 스레드를 생성하는 것은 비싸다는 것에주의하십시오. 데이터를 순차적으로 처리하는 것이 스레드를 만드는 것보다 시간이 더 걸릴 가능성이 큽니다. 따라서 쉽게 병렬 처리가 가능할 것이라고 맹목적으로 바라지 마십시오. – Mehrdad

답변

28

즉시 함수가 반환로는 결합 가능한 스레드 객체를 파괴하지 않아야합니다, 실제로 오류를

가 발생합니다. 나중에 스레드의 완료를 기다릴 필요가없는 경우,이를 분리 :

std::thread thread(ClientLoop,clientSocket); 
thread.detach(); 
// OK to destroy now 

나중에 가입 할 필요가 있다면, 당신은 예를 들어, 루프 이상 지속 어딘가에 보관해야합니다

std::vector<std::thread> threads; 
while (whatever){ 
    clientSocket = accept(listenSocket, nullptr, nullptr); 
    threads.emplace_back(ClientLoop,clientSocket); 
} 

// later 
for (std::thread & t : threads) { 
    t.join(); 
} 

// OK to destroy now 
threads.clear(); 

작동이 방법은 있지만 메모리 누수가없는 경우 궁금하다.

그래, 그게 새어. 각 new은 스레드 개체를 만들고 포인터를 삭제하거나 스마트 포인터에 할당하여 처리하지 않고 삭제합니다. 주석에서 언급했듯이 메모리 누수뿐만 아니라 일부 시스템에서는 더 많은 리소스가 부족한 스레드 핸들도 있습니다. 잠시 후에 더 이상 스레드를 시작할 수 없다는 것을 알 수 있습니다.

스레드 분리는 누설없이 백그라운드에서 실행되도록하는 방법입니다. 이로 인해 스레드가 완료 될 때 리소스를 해제합니다.

+5

그것은 단지 메모리 누수가 아닙니다. 스레드는 일반적으로 시스템 리소스를 조인 할 때까지 사용하거나 분리 된 경우 종료합니다. 이 경우에는 메모리가 부족하기 전에 너무 많은 스레드로 인해 실패하기 시작할 수있는 좋은 기회가 있습니다. –

+0

덕분에 모든 스레드를 동기화 할 필요가 없기 때문에 detach()를 사용했습니다. – Tomas

+0

분리 스레드는 데몬 스레드라고도 부릅니까? – 0x499602D2

9

루프에서 스레드를 만드는 데는 문제가 없지만 로컬 변수 인 경우 루프 끝에 스레드를 파괴하는 데 문제가있을 수 있습니다. 합법적으로 소멸시키기 위해서는 스레드 객체 이 detach ed, join ed이거나 이동되어야합니다. 스레드가 이고 단순히 “이라면 ”을 잊어 버리십시오. 나중에 을 동기화하면 (심지어 정상 종료의 경우에도) 스레드를 생성 한 후 std::thread::detach을 호출하면됩니다. 그렇지 않으면 std::vector<std::thread>에 넣을 수 있습니다. 따라서 을 찾고 나중에 찾을 수 있습니다.

+0

... 또는 소멸자에서 사용자 정의 동작을 사용하여 RAII- 오브젝트에 랩하십시오. – Drop

+0

join_all로 충분하지 않아야합니까? – deW1

+0

감사합니다, 이것은 또한 정답입니다. 그러나 나는 더 많은 설명이 필요하기 때문에 다른 하나를 표시해야했습니다. – Tomas

5

마치 스레드의 수명을 관리하고 싶지 않은 것처럼 보입니다 (거의 항상 실수입니다). 정확하게 오류가 무엇

while (true){ 
    cout << "Waiting for new connections" << endl; 
    clientSocket = accept(listenSocket, nullptr, nullptr); 
    cout << "Client connected" << endl; 
    thread t(ClientLoop,clientSocket); 
    t.detach(); // detach the actual thread from its std::thread handle 
} 
+2

'이것은 거의 항상 실수입니다.'- 왜? 그것은 accept() 쓰레드이고, 아마도 프로세스 수명 동안 실행될 필요가있을 것이다. 프로세스 수명 스레드는 평범하지 않습니다. –

+3

짧은 대답은 무제한 스레드의 생성이 확장 가능한 솔루션이 아니라는 것입니다. 결국 로직을 스레드 풀을 사용하여 비동기 모델로 변환하거나 일부 상한선을 기준으로 연결을 조절해야합니다. –

+0

실제로 무제한 스레드를 생성 할 것을 제안했다면 괜찮은 주석이됩니다. 이후 나는 .... –

관련 문제