main ()이 종료되면 분리 된 스레드는 어떻게됩니까?
내가 시작한 std::thread
다음 detach()
스레드를 실행 한다고 가정 하면 스레드 std::thread
가 한 번 표현 했지만 스레드가 계속 실행되지 않습니다 .
또한 프로그램에 분리 된 스레드 1 을 연결하기위한 신뢰할 수있는 프로토콜이 없으므로 분리 된 스레드가 main()
종료 될 때에도 계속 실행 됩니다.
표준에서 (더 정확하게는 N3797 C ++ 14 초안에서) 아무것도 찾을 수 없으며, 1.10도 30.3도 관련 문구를 포함하지 않아야합니다.
1 또 다른, 아마도 동등한 질문은 "연결 해제 된 스레드를 다시 결합 할 수 있습니까?"입니다. 결합하려는 어떤 프로토콜이든 스레드가 계속 실행되는 동안 신호 부분을 수행해야하고 OS 스케줄러가 수신 측에서 스레드가 실제로 완료되었음을 확실하게 감지 할 수있는 방법이없는 신호 처리 직후 스레드를 1 시간 동안 휴면 상태로두기로 결정합니다.
부족하면 main()
분리 된 스레드가 실행하는 것은 정의되지 않은 동작은 다음 어떤 의 사용은 std::thread::detach()
메인 스레드가 종료하지 않는 한 정의되지 않은 동작이다 (2) .
따라서 main()
분리 된 스레드가 실행 중이면 정의 된 효과 가 있어야합니다 . 질문 : 어디 합니다 (에 C ++ 표준 이 아닌 POSIX가 아닌 OS 워드 프로세서, ...) 정의 된 효과가 있습니다.
2 분리 된 스레드는 (의미에서 std::thread::join()
) 결합 될 수 없습니다 . 분리 된 스레드에서 결과를 기다릴 수 있습니다 (예 :에서를 통해 std::packaged_task
또는 세마포어 또는 플래그 및 조건 변수를 통해) 스레드가 실행을 완료 한 것은 아닙니다 . 당신이 스레드의 첫 번째 자동 개체의 소멸자에 신호 부분을 넣어하지 않는 사실,이 것 , 일반적으로 실행되는 코드 (소멸자) 일 후 시그널링 코드입니다. OS가 메인 스레드가 결과를 소비하고 분리 된 스레드가 소멸자를 실행하기 전에 종료하도록 스케줄하면 Wis는 어떻게됩니까?
원래 질문 "종료시 분리 된 스레드는 어떻게됩니까"에 대한 답변 main()
은 다음과 같습니다.
표준이 중지되었다고 말하지 않기 때문에 계속 실행되며, 다른 스레드 나 정적 객체의 (automatic | thread_local) 변수에 닿지 않는 한 잘 정의되어 있습니다.
이것은 스레드 관리자를 정적 객체로 허용 할 수있는 것으로 보입니다 ( [basic.start.term] / 4의 설명 은 포인터에 대한 @dyp 덕분에 많은 것을 말합니다).
정적 객체의 소멸이 완료되면 문제가 발생합니다. 실행은 신호 핸들러에 허용 된 코드 만 실행할 수있는 영역으로 들어갑니다 ( [basic.start.term] / 1, 1 번째 문장 ). C ++ 표준 라이브러리 중 <atomic>
라이브러리 ( [support.runtime] / 9, 2 번째 문장 ) 만 해당됩니다. 특히, 일반 - 인 것을 제외한다 condition_variable
(이 부분 아니기 때문에 그것의 여부를 그 구현 정의, 신호 처리기에서 사용할 저장이다 <atomic>
).
이 시점에서 스택을 풀지 않으면 정의되지 않은 동작을 피하는 방법을 찾기가 어렵습니다.
두 번째 질문 "분리 된 스레드를 다시 결합 할 수 있음"에 대한 대답은 다음과 같습니다.
네,와 *_at_thread_exit
기능의 가족 ( notify_all_at_thread_exit()
, std::promise::set_value_at_thread_exit()
, ...).
질문의 각주 [2]에 언급 된 바와 같이, 조건 변수 또는 세마포어 또는 원자 카운터를 시그널링하는 것만으로는 분리 된 스레드를 결합하기에 충분하지 않다 (수행 전에 실행 이 끝났음을 보장한다는 의미 에서) 일반적으로, 예를 들어 notify_all()
조건 변수, 특히 자동 및 스레드 로컬 객체의 소멸자 이후에 더 많은 코드가 실행될 것이기 때문에, 상기 스레드는 상기 스레드에 의한 시그널링이다 .
(스레드가 수행하는 마지막으로 신호 실행 후 자동으로 thread 로컬 객체의 소멸자가 -일어난 것은 )이 무엇인가 _at_thread_exit
기능의 가족을 위해 설계되었습니다.
따라서, 표준이 요구하는 것 이상의 어떤 구현 보증의 부재에서 정의되지 않은 동작을 방지하기 위해, 당신은 (수동)를 가진 분리 된 스레드에 가입해야합니다 _at_thread_exit
시그널링을하는 기능 또는 분리 된 쓰레드가 실행할 수 있도록 단지 에 대한 안전 할 것입니다 코드를 시그널 핸들러도 마찬가지입니다.
스레드 분리
에 따르면 std::thread::detach
:
실행 스레드를 스레드 개체와 분리하여 실행을 독립적으로 계속할 수 있습니다. 스레드가 종료되면 할당 된 모든 리소스가 해제됩니다.
보낸 사람 pthread_detach
:
pthread_detach () 함수는 스레드가 종료 될 때 스레드에 대한 스토리지를 회수 할 수 있음을 구현에 표시해야합니다. 스레드가 종료되지 않은 경우 pthread_detach ()는 종료되지 않습니다. 동일한 대상 스레드에서 여러 pthread_detach () 호출의 영향은 지정되지 않았습니다.
스레드 분리는 주로 애플리케이션이 스레드가 완료 될 때까지 기다릴 필요가없는 경우 (예 : 프로세스 종료까지 실행해야하는 데몬)에 필요한 리소스 절약을위한 것입니다.
- 응용 프로그램 측면 핸들을 해제하려면 :
std::thread
개체를 조인하지 않고 범위를 벗어날 수 있습니다. 이로 인해 일반적으로std::terminate()
소멸이 발생합니다. - OS가 스레드를 종료하자마자 스레드 특정 리소스 ( TCB )를 자동으로 정리할 수있게하려면 명시 적으로 지정 했으므로 나중에 스레드 결합에 관심이 없으므로 이미 분리 된 스레드에 참여할 수 없습니다.
죽이는 실
프로세스 종료시 동작은 메인 스레드의 동작과 동일하며 적어도 일부 신호를 포착 할 수 있습니다. 주 스레드의 신호 처리기 호출 내에서 다른 스레드를 결합하거나 종료 할 수 있으므로 다른 스레드가 신호를 처리 할 수 있는지 여부는 그렇게 중요하지 않습니다. (관련 질문 )
이미 언급했듯이 분리 여부에 관계없이 모든 스레드는 대부분의 OS에서 프로세스와 함께 죽습니다 . 프로세스 자체는 신호를 발생 exit()
시키거나 호출 하거나 주 기능에서 복귀 함으로써 종료 될 수 있습니다 . 그러나 C ++ 11은 기본 OS의 정확한 동작을 정의 할 수 없으며, Java VM 개발자는 이러한 차이를 어느 정도 추상화 할 수 있습니다. AFAIK, 이국적인 프로세스 및 스레딩 모델은 일반적으로 고대 플랫폼 (C ++ 11이 이식되지 않을 것임) 및 특수한 및 / 또는 제한된 언어 라이브러리 구현 및 제한된 언어 지원을 가질 수있는 다양한 임베디드 시스템에서 발견됩니다.
스레드 지원
If threads aren't supported std::thread::get_id()
should return an invalid id (default constructed std::thread::id
) as there's a plain process, which does not need a thread object to run and the constructor of a std::thread
should throw a std::system_error
. This is how I understand C++11 in conjunction with today's OSes. If there's an OS with threading support, which doesn't spawn a main thread in its processes, let me know.
Controlling Threads
If one needs to keep control over a thread for proper shutdown, one can do that by using sync primitives and/or some sort of flags. However, In this case, setting a shutdown flag followed by a join is the way I prefer, since there's no point in increasing complexity by detaching threads, as the resources would be freed at the same time anyway, where the few bytes of the std::thread
object vs. higher complexity and possibly more sync primitives should be acceptable.
The fate of the thread after the program exits is undefined behavior. But a modern operating system will clean up all threads created by the process on closing it.
When detaching an std::thread
, these three conditions will continue to hold:
*this
no longer owns any threadjoinable()
will always equal tofalse
get_id()
will equalstd::thread::id()
Consider the following code:
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
void thread_fn() {
std::this_thread::sleep_for (std::chrono::seconds(1));
std::cout << "Inside thread function\n";
}
int main()
{
std::thread t1(thread_fn);
t1.detach();
return 0;
}
Running it on a Linux system, the message from the thread_fn is never printed. The OS indeed cleans up thread_fn()
as soon as main()
exits. Replacing t1.detach()
with t1.join()
always prints the message as expected.
When the main thread (that is, the thread that runs the main() function) terminates, then the process terminates and all other threads stop.
Reference: https://stackoverflow.com/a/4667273/2194843
To allow other threads to continue execution, the main thread should terminate by calling pthread_exit() rather than exit(3). It's fine to use pthread_exit in main. When pthread_exit is used, the main thread will stop executing and will remain in zombie(defunct) status until all other threads exit. If you are using pthread_exit in main thread, cannot get return status of other threads and cannot do clean-up for other threads (could be done using pthread_join(3)). Also, it's better to detach threads(pthread_detach(3)) so that thread resources are automatically released on thread termination. The shared resources will not be released until all threads exit.
참고URL : https://stackoverflow.com/questions/19744250/what-happens-to-a-detached-thread-when-main-exits
'Programming' 카테고리의 다른 글
파이썬에서 클래스 메소드 내에서 "정적"클래스 변수에 액세스하는 방법 (0) | 2020.06.23 |
---|---|
학습을위한 훌륭한 오픈 소스 장고 프로젝트 (0) | 2020.06.22 |
간단한 데이터베이스 엔진을 작성하는 방법 (0) | 2020.06.22 |
타사 OAuth 공급자를 통한 인증을 허용하면서 OAuth로 REST API 보안 유지 (DotNetOpenAuth 사용) (0) | 2020.06.22 |
HATEOAS (REST 아키텍처)에 대한 실제 예 (0) | 2020.06.22 |