"_thread" --- 저수준 스레드 API
*******************************

======================================================================

이 모듈은 다중 스레드(*경량 프로세스 (light-weight processes)* 나 *태
스크 (tasks)*라고도 합니다)로 작업하는데 필요한 저수준 기본 요소를 제
공합니다 --- 전역 데이터 공간을 공유하는 여러 개의 제어 스레드를 뜻합
니다. 동기화를 위해서, 간단한 록(*뮤텍스 (mutexes)*나 *이진 세마포어
(binary semaphores)*라고도 합니다)이 제공됩니다. "threading" 모듈은 이
모듈 위에 구축되어 사용하기 쉬운 고수준의 스레딩 API를 제공합니다.

버전 3.7에서 변경: 이 모듈은 선택 사항이었지만, 이제는 항상 사용할 수
있습니다.

이 모듈은 다음 상수와 함수를 정의합니다:

exception _thread.error

   스레드 특정 에러에서 발생합니다.

   버전 3.3에서 변경: 이것은 이제 내장 "RuntimeError"의 동의어입니다.

_thread.LockType

   이것은 록 객체의 형입니다.

_thread.start_new_thread(function, args[, kwargs])

   새 스레드를 시작하고 식별자를 반환합니다. 스레드는 인자 목록
   *args*(튜플이어야 합니다)로 함수 *function*을 실행합니다. 선택적
   *kwargs* 인자는 키워드 인자 딕셔너리를 지정합니다.

   함수가 반환되면, 스레드는 조용히 종료합니다.

   함수가 처리되지 않은 예외로 종료되면, 예외를 처리하기 위해
   "sys.unraisablehook()"이 호출됩니다. 훅 인자의 *object* 어트리뷰트
   는 *function*입니다. 기본적으로, 스택 트레이스가 인쇄된 다음 스레드
   가 종료합니다 (하지만 다른 스레드는 계속 실행됩니다).

   함수가 "SystemExit" 예외를 발생시키면, 조용히 무시됩니다.

   Raises an auditing event "_thread.start_new_thread" with arguments
   "function", "args", "kwargs".

   버전 3.8에서 변경: "sys.unraisablehook()"은 이제 처리되지 않은 예외
   를 처리하는 데 사용됩니다.

_thread.interrupt_main(signum=signal.SIGINT, /)

   메인 스레드에 도달한 시그널의 효과를 시뮬레이트합니다. 스레드는 이
   함수를 사용하여 메인 스레드를 인터럽트 할 수 있지만, 중단이 즉시 일
   어난다는 보장은 없습니다.

   If given, *signum* is the number of the signal to simulate. If
   *signum* is not given, "signal.SIGINT" is simulated.

   주어진 시그널이 파이썬에 의해 처리되지 않으면 ("signal.SIG_DFL"이나
   "signal.SIG_IGN"으로 설정됩니다), 이 함수는 아무것도 하지 않습니다.

   버전 3.10에서 변경: The *signum* argument is added to customize the
   signal number.

   참고:

     This does not emit the corresponding signal but schedules a call
     to the associated handler (if it exists). If you want to truly
     emit the signal, use "signal.raise_signal()".

_thread.exit()

   "SystemExit" 예외를 발생시킵니다. 잡히지 않으면, 스레드가 조용히 종
   료되도록 합니다.

_thread.allocate_lock()

   새로운 록 객체를 반환합니다. 록의 메서드는 아래에 설명되어 있습니다
   . 록은 초기에 잠금 해제되어 있습니다.

_thread.get_ident()

   현재 스레드의 '스레드 식별자(thread identifier)'를 반환합니다. 이것
   은 0이 아닌 정수입니다. 그 값은 직접적인 의미가 없습니다; 이것은 예
   를 들어 스레드 특정 데이터의 딕셔너리를 인덱싱하는 데 사용되는 매직
   쿠키로 사용하려는 의도입니다. 스레드 식별자는 스레드가 종료되고 다
   른 스레드가 만들어질 때 재활용될 수 있습니다.

_thread.get_native_id()

   커널에 의해 할당된 현재 스레드의 네이티브 정수 스레드 ID를 반환합니
   다. 이것은 음수가 아닌 정수입니다. 이 값은 시스템 전반에 걸쳐 이 특
   정 스레드를 고유하게 식별하는 데 사용될 수 있습니다 (스레드가 종료
   될 때까지, 그 후에는 값이 OS에 의해 재활용될 수 있습니다).

   가용성: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX,
   DragonFlyBSD, GNU/kFreeBSD.

   Added in version 3.8.

   버전 3.13에서 변경: Added support for GNU/kFreeBSD.

_thread.stack_size([size])

   새로운 스레드를 만들 때 사용된 스레드의 스택 크기를 반환합니다. 선
   택적 *size* 인자는 이후에 만들어지는 스레드에 사용할 스택 크기를 지
   정하며, 0(플랫폼 또는 구성된 기본값을 사용합니다)이나 최소
   32,768(32 KiB)의 양의 정숫값이어야 합니다. *size*를 지정하지 않으면
   0이 사용됩니다. 스레드 스택 크기 변경이 지원되지 않으면,
   "RuntimeError"가 발생합니다. 지정된 스택 크기가 유효하지 않으면,
   "ValueError"가 발생하고, 스택 크기는 변경되지 않습니다. 32 KiB는 현
   재 인터프리터 자체에 충분한 스택 공간을 보장하기 위해 지원되는 최소
   스택 크기 값입니다. 일부 플랫폼에서는 스택 크기 값에 특별한 제한이
   있을 수 있습니다, 가령 최소 스택 크기 > 32KB를 요구하거나 시스템 메
   모리 페이지 크기의 배수로 할당하는 것을 요구할 수 있습니다 - 자세한
   내용은 플랫폼 설명서를 참조하십시오 (4 KiB 페이지가 일반적입니다;
   더 구체적인 정보가 없으면 스택 크기로 4096의 배수를 사용하는 것이
   제안된 방법입니다).

   가용성: Windows, pthreads.

   Unix platforms with POSIX threads support.

_thread.TIMEOUT_MAX

   "Lock.acquire"의 *timeout* 매개 변수에 허용되는 최댓값. 이 값보다
   큰 timeout을 지정하면 "OverflowError"가 발생합니다.

   Added in version 3.2.

록 객체에는 다음과 같은 메서드가 있습니다:

lock.acquire(blocking=True, timeout=-1)

   선택적 인자가 아무것도 없으면, 이 메서드는 조건 없이 록을 획득합니
   다, 필요하면 다른 스레드가 록을 해제할 때까지 대기합니다 (한 번에
   하나의 스레드만 록을 획득할 수 있습니다 --- 이것이 록의 존재 이유입
   니다).

   *blocking* 인자가 있으면, 행동은 그 값에 따라 다릅니다: 거짓이면 대
   기하지 않고 즉시 획득할 수 있을 때만 록이 획득되고, 참이면 위와 같
   이 록이 조건 없이 획득됩니다.

   부동 소수점 *timeout* 인자가 있고 양수이면, 반환하기 전에 대기할 최
   대 시간을 초로 지정합니다. 음의 *timeout* 인자는 제한 없는 대기를
   지정합니다. *blocking*이 거짓이면 *timeout*을 지정할 수 없습니다.

   록이 성공적으로 획득되면 반환 값은 "True"이고, 그렇지 않으면
   "False"입니다.

   버전 3.2에서 변경: *timeout* 매개 변수가 추가되었습니다.

   버전 3.2에서 변경: 록 획득은 이제 POSIX의 시그널에 의해 중단될 수
   있습니다.

lock.release()

   록을 해제합니다. 록은 반드시 이전에 획득된 것이어야 하지만, 반드시
   같은 스레드에 의해 획득된 것일 필요는 없습니다.

lock.locked()

   록의 상태를 반환합니다: 어떤 스레드에 의해 획득되었으면 "True", 그
   렇지 않으면 "False"를 반환합니다.

이러한 메서드 외에도, "with" 문을 통해 록 객체를 사용할 수도 있습니다,
예를 들어:

   import _thread

   a_lock = _thread.allocate_lock()

   with a_lock:
       print("a_lock is locked while this executes")

**주의 사항:**

* Interrupts always go to the main thread (the "KeyboardInterrupt"
  exception will be received by that thread.)

* "sys.exit()"를 호출하거나 "SystemExit" 예외를 발생시키는 것은
  "_thread.exit()"를 호출하는 것과 동등합니다.

* It is platform-dependent whether the "acquire()" method on a lock
  can be interrupted (so that the "KeyboardInterrupt" exception will
  happen immediately, rather than only after the lock has been
  acquired or the operation has timed out). It can be interrupted on
  POSIX, but not on Windows.

* 메인 스레드가 종료할 때, 다른 스레드가 살아남는지는 시스템이 정의합
  니다. 대부분 시스템에서, "try" ... "finally" 절을 실행하거나 객체 파
  괴자(destructor)를 실행하지 않고 강제 종료됩니다.
