C ++ 11에서 스레드를 어떻게 종료합니까?


137

스레드를 올바르게 종료하거나 "종료"명령에 응답 할 필요가 없습니다. 순수한 C ++ 11을 사용하여 스레드를 강제 종료하는 데 관심이 있습니다.


7
다음은이 주제에 대한 좋은 질문입니다 : stackoverflow.com/questions/2790346/c0x-thread-interruption "모든 언어 사양은 지원 언어에 내장되지 않은 것을 말한다는"
네마냐 붕소

답변:


138
  1. std::terminate()어떤 스레드에서든 호출 할 수 있으며 참조하는 스레드가 강제 종료됩니다.

  2. 당신은을 준비 할 수 ~thread()개입하지 않고, 타겟 thread의 개체에 실행하는 join()detach()그 객체에. 옵션 1과 동일한 효과가 있습니다.

  3. 예외를 발생시키는 소멸자가있는 예외를 디자인 할 수 있습니다. 그런 다음 강제 종료 될 때 대상 스레드가이 예외를 처리하도록 배열하십시오. 이것의 까다로운 부분은 대상 스레드 가이 예외를 발생시키는 것입니다.

옵션 1과 2는 프로세스 내 리소스를 누출시키지 않지만 모든 스레드 를 종료 합니다 .

옵션 3은 아마도 리소스를 유출하지만 대상 스레드가 예외를 처리하는 데 동의해야하기 때문에 부분적으로 협력 적입니다.

C ++ 11에는 다중 스레드 프로그램에서 단일 스레드를 비협조적으로 죽이는 (즉, 모든 스레드를 죽이지 않고) 이식 할 수있는 방법이 없습니다. 이러한 기능을 디자인하려는 동기는 없었습니다.

A std::thread는이 멤버 함수를 가질 수 있습니다.

native_handle_type native_handle();

이것을 사용하여 원하는 작업을 수행하기 위해 OS 종속 함수를 호출 할 수 있습니다. 예를 들어 Apple OS에서이 기능은 존재하며 native_handle_type입니다 pthread_t. 성공하면 리소스가 유출 될 수 있습니다.


2
"프로세스 내부 리소스 누수 안" 에 대한 약간의 nitpick : 물론 프로세스 종료 후 OS가 모든 리소스를 회수한다는 것은 사실이지만 , 프로그램에 관한 한 리소스 누출됩니다. 일반적으로 관련이 없지만 경우에 따라 여전히 문제가 될 수 있습니다. std::terminate정적 소멸자를 호출하거나 출력 버퍼를 플러시하지 않으므로 리소스가 해제되는 순서가 잘 정의되어 있지 않거나 데이터가 사용자에게 표시되거나 영구 저장소에 기록되거나 심지어 일관되고 완전합니다.
데이먼

6
전화 exit()하거나 abort()동일한 전체 효과를 낼 수도 있습니다 .
n. '대명사'm.

2
# 1은 농담이며 @ChrisDodd가 옳습니다. 농담은 # 3의 첫 문장에서 답에 설명되어 있습니다. 또한 Nanno Langstraat의 답변과 그 아래의 의견을 참조하십시오.
Howard Hinnant

43

@Howard Hinnant의 답변은 정확 하고 포괄적입니다. 그러나 std::terminate()(전체 프로세스) @AlexanderVX가 생각한 "종료"와 동일한 이름을 갖기 때문에 너무 빨리 읽으면 잘못 이해할 수 있습니다 (1 스레드).

요약 : "1 스레드 + 강제 종료 (타겟 스레드가 협력하지 않음) + 순수 C ++ 11 = 안됩니다."


14
아, 내 # 1은 정말 재밌어요. 어떤 스레드를 강제 종료할지 지정할 필요가 없습니다. 시스템은 당신이 어떤 것을 강하게 끝내고 싶은지를 마술처럼 알고 있습니다!
Howard Hinnant

8
그렇습니다. std::terminate()대답은 고전적인 장난스러운 Djinn 이야기와 같습니다. 그것은 그가 의도 한 방식이 아니더라도 OP에 대한 서한에 대한 모든 것을 이행한다 . 절제된 유머가 나를 웃게 만들었습니다. :-)
Nanno Langstraat

2
무고한 C ++ 초보자가 희망을 너무 멀리 / 너무 길지 않도록 막아야합니다.
Nanno Langstraat

2
우아하게 언급했습니다. :-)
Howard Hinnant 2012 년

내가 읽을 때까지 dammnit @NannoLangstraat ... 나는 높은 희망을 가지고 있었다 (물론 오, ..lol +1 모든 주위를 :)
code_fodder

13

이 질문은 실제로 멀티 스레딩 개념에 대한보다 깊은 이해와 올바른 이해를 바탕으로이 주제에 대한 통찰력을 제공합니다. 실제로 비동기 스레드를 사용하지 말라고 경고하지 않고 갑자기 스레드를 종료하는 기능을 제공하는 언어 나 운영 체제가 없습니다. 그리고 이러한 모든 실행 환경은 개발자에게 강력하게 조언하거나 협력 또는 동기식 스레드 종료를 기반으로 빌드 멀티 스레딩 응용 프로그램을 요구합니다. 이 일반적인 결정과 조언의 이유는 모두 동일한 일반 멀티 스레딩 모델을 기반으로하기 때문입니다.

멀티 프로세싱과 멀티 스레딩 개념을 비교하여 두 번째 개념의 장단점을보다 잘 이해하겠습니다.

멀티 프로세싱은 전체 실행 환경을 운영 체제에서 제어하는 ​​완전히 격리 된 프로세스 세트로 분할한다고 가정합니다. 프로세스는 프로세스의 로컬 메모리와 프로세스 내부의 데이터 및 파일, 소켓, 동기화 개체와 같은 모든 시스템 리소스를 포함하여 실행 환경 상태를 통합하고 격리합니다. 격리는 프로세스 경계에 의한 결함 전파를 제한하기 때문에 프로세스의 매우 중요한 특성입니다. 즉, 어떤 프로세스도 시스템에서 다른 프로세스의 일관성에 영향을 줄 수 없습니다. 프로세스 동작에 대해서도 마찬가지이지만 덜 제한적이고 흐리게 처리됩니다. 이러한 환경에서는 모든 프로세스가 임의의 "임의"순간에 종료 될 수 있습니다.

반대로 멀티 스레딩은 동일한 프로세스에서 여러 스레드를 실행한다고 가정합니다. 그러나이 모든 스레드는 동일한 격리 상자를 공유하며 프로세스의 내부 상태에 대한 운영 체제 제어가 없습니다. 결과적으로 모든 스레드는 전역 프로세스 상태를 변경하고 손상시킬 수 있습니다. 동시에 스레드의 상태가 스레드를 완전히 죽이기에 안전한 것으로 알려진 지점은 응용 프로그램 논리에 따라 다르며 운영 체제 나 프로그래밍 언어 런타임에 대해서는 알려지지 않았습니다. 결과적으로 임의의 순간에 스레드 종료는 실행 경로의 임의의 지점에서 스레드를 종료하는 것을 의미하며 프로세스 전체의 데이터 손상, 메모리 및 핸들 누수로 쉽게 이어질 수 있습니다.

이 때문에 일반적인 접근 방식은 개발자가 동기식 또는 협업 스레드 종료를 구현하도록하는 것입니다. 여기서 하나의 스레드가 다른 스레드 종료를 요청할 수 있고 잘 정의 된 지점의 다른 스레드가이 요청을 확인하고 잘 정의 된 상태에서 종료 절차를 시작할 수 있습니다 안전하고 일관된 방식으로 모든 글로벌 시스템 전체 리소스 및 로컬 프로세스 전체 리소스를 공개합니다.


8
이것은 매우 유용한 답변이 아닙니다. 멀티 프로세싱은 여기서 관련이 없으며 멀티 스레딩에 대한 관찰은 다소 광범위합니다.
MSalters

4
내가 말하고 세부적으로 말한 것은 멀티 스레딩 모델이 공식적인 스레드 종료 방법을 제공하지 않는다는 것입니다. C ++은 메모리 모델, 멀티 스레딩 모델 등 명확한 모델을 따르기를 원합니다. 강력한 스레드 종료 방법은 본질적으로 안전하지 않습니다. C ++ 표준위원회가 C ++에위원회를 추가하도록 강요한다면, "Method terminate ()는 스레드 실행을 종료합니다. 동작은 정의되지 않습니다." ".
ZarathustrA

C #에는이 기능이 있습니다.
Derf Skren

@Derf Skren "실제로 사용하지 말라고 경고하지 않고 비동기식으로 스레드를 종료 할 수있는 기능을 제공하는 언어 나 운영 체제는 없습니다"(c) ZarathustrA "주의 : 중요! Thread.Abort 메소드는주의해서 사용해야합니다. 특히 현재 스레드 이외의 스레드를 중단하기 위해 호출 할 때 어떤 코드가 실행되었거나 실행되지 않았는지 알 수 없습니다 ... "(c) Microsoft 링크 : docs.microsoft.com/en-us/dotnet/ api /…
ZarathustrA

11

OS 종속 함수를 사용하여 C ++ 스레드를 종료하는 팁 :

  1. std::thread::native_handle()단지 호출하기 전에 스레드의 유효 기본 핸들 타입을 얻을 수 있습니다 join()또는 detach(). 그 후 native_handle()0을 반환합니다- pthread_cancel()코어 덤프됩니다.

  2. 기본 스레드 종료 기능 (예 :)을 효과적으로 호출하려면 또는 pthread_cancel()을 호출하기 전에 기본 핸들을 저장해야합니다 . 따라서 네이티브 터미네이터에는 항상 유효한 유효한 네이티브 핸들이 있습니다.std::thread::join()std::thread::detach()

자세한 설명은 http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread 를 참조하십시오 .


5

종료 해야하는 스레드가 모든 종류의 대기 모드이거나 무거운 작업을 수행하고 있다고 생각합니다. "순진한"방법을 사용하는 것이 좋습니다.

전역 부울을 정의하십시오.

std::atomic_bool stop_thread_1 = false;

스레드가 자연스럽게 종료 될 때까지 호출 스택의 모든 함수가 리턴되도록 다음 키 포인트 (또는 이와 유사한 코드)를 여러 키 포인트에 넣으십시오.

if (stop_thread_1)
    return;

그런 다음 다른 (주) 스레드에서 스레드를 중지하십시오.

stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.