IT공부/IT서적

[뇌를 자극하는 윈도우즈 시스템 프로그래밍] 12장. 쓰레드의 생성과 소멸

shine94 2025. 2. 13. 20:49

* 해당 글은 윤성우의 뇌를 자극하는 윈도우즈 시스템 프로그래밍 도서를 읽고 정리한 글입니다

   https://product.kyobobook.co.kr/detail/S000001223395

 

뇌를 자극하는 윈도우즈 시스템 프로그래밍 | 윤성우 - 교보문고

뇌를 자극하는 윈도우즈 시스템 프로그래밍 |

product.kyobobook.co.kr

 

 

 

 

* CreateThread 함수

   쓰레드 생성

HANDLE CreateThread(
  [in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  [in]            SIZE_T                  dwStackSize,
  [in]            LPTHREAD_START_ROUTINE  lpStartAddress,
  [in, optional]  __drv_aliasesMem LPVOID lpParameter,
  [in]            DWORD                   dwCreationFlags,
  [out, optional] LPDWORD                 lpThreadId
);

 


lpThreadAttributes

 : 반환된 핸들을 자식 프로세스에게 상속할 수 있는지의 여부를 결정하는 보안 속성 지정
dwStackSize

 : 스택의 초기 사이즈(바이트)
lpStartAddress

 : 쓰레드 함수
lpParameter

 : 쓰레드 함수 전달인자
dwCreationFlags

 : 쓰레드 생성을 제어하는 플래그
lpThreadId

 : 쓰레드 Id 반환

https://learn.microsoft.com/ko-kr/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread

 

CreateThread 함수(processthreadsapi.h) - Win32 apps

호출 프로세스의 가상 주소 공간 내에서 실행할 스레드를 만듭니다.

learn.microsoft.com

 

* 쓰레드의 흐름을 예측은 불가능하다

   ㄴ 초보 프로그래머가 범하는 과오 중 하나임 - 쓰레드의 흐름을 예측하려고 하는 것

 

* 프로세스가 만들 수 있는 쓰레드의 수는 가상 메모리에 의해 제한된다

   기본적으로 모든 쓰레드에는 1MB의 스택 공간을 가지고 있어

   /3GB boot.ini 옵션 없이는 32비트 시스템에서는 2,048개 이상의 쓰레드를 만들 수 없다

   만약에 기본 스택 크기를 줄인다면, 더 많은 스레드를 만들 수 있다

 

 

* 쓰레드의 소멸

1. return 이용

 

2. ExitThread 함수 호출

void ExitThread(
  [in] DWORD dwExitCode
);

 

dwExitCode

 : 쓰레드의 종료 코드

 

https://learn.microsoft.com/ko-kr/windows/win32/api/processthreadsapi/nf-processthreadsapi-exitthread

 

ExitThread 함수(processthreadsapi.h) - Win32 apps

호출 스레드를 종료합니다.

learn.microsoft.com

 

3. TerminateThread 함수 호출

BOOL TerminateThread(
  [in, out] HANDLE hThread,
  [in]      DWORD  dwExitCode
);

 


hThread

: 종료할 쓰레드에 대한 핸들
dwExitCode

 : 쓰레드의 종료 코드

 

https://learn.microsoft.com/ko-kr/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread

 

TerminateThread 함수(processthreadsapi.h) - Win32 apps

스레드를 종료합니다.

learn.microsoft.com

 

* 쓰레드는 메모리를 공유(힙 영역, 데이터 영역, 코드 영역)한다

   따라서, 동시 접근에 있어서 문제점이 발생할 수 있다

 

   쓰레드가 동시에  실행되는 것처럼 보이지만 빨라서 그렇게 보이는 것일 뿐 사실은 돌아가면서 실행된다

   ㄴ 따라서,

        (1) 실행중인 스레드의 변경에 의해서 컨텍스트 스위칭은 빈번하게 발생한다

        (2) 둘 이상의 쓰레드가 같은 메모리 영역을 동시에 참조하는 것은 문제를 일으킬 가능성이 매우 높다

 

* 프로세스로부터의 쓰레드 분리한다

   프로세스가 소유하는 쓰레드의 핸들을 반환함으로써 쓰레드의 Usage Count를 1로 두겠다는 뜻

   이는 쓰레드가 종료되는 시점에 쓰레드의 리소스를 반환하기 위함

 

* strtok 함수 문제점

   - 내부적으로 전역 static 변수를 사용하여 상태를 저장

   - 멀티 쓰레드 환경에서 여러 쓰레드가 동일한 문자열을 strtok로 처리하면,

      한 쓰레드에서 상태가 변경될 수 있어 예기치 않은 동작일 발생할 수 있다

 

* strtok 함수 문제점을 개선한 strtok_s 함수

   - 내부 상태를 함수 외부에서 직접 관리할 수 있도록 context 포인터를 추가로 받는다

   - 각 쓰레드가 별도의 context를 유지하면,

      동일한 문자열을 여러 쓰레드에서 동시에 처리해도 충돌이 발생하지 않는다

 

char* strtok_s(
   char* str,
   const char* delimiters,
   char** context
);


str

 : 찾을 토큰 또는 토큰이 포함된 문자열
delimiters

 : 사용할 구분 기호 문자 집합

context

 : 함수 호출 간에 위치 정보를 저장하는데 사용

 

https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/reference/strtok-s-strtok-s-l-wcstok-s-wcstok-s-l-mbstok-s-mbstok-s-l?view=msvc-170

 

strtok_s, _strtok_s_l, wcstok_s, _wcstok_s_l, _mbstok_s, _mbstok_s_l

자세한 정보: strtok_s, _strtok_s_l, wcstok_s, _wcstok_s_l, _mbstok_s, _mbstok_s_l

learn.microsoft.com

 

* _beginthread 함수

   쓰레드 생성

   쓰레드를 위해 독립적인 메모리 블록을 할당

uintptr_t _beginthreadex(
   void *security,
   unsigned stack_size,
   unsigned ( __stdcall *start_address )( void * ),
   void *arglist,
   unsigned initflag,
   unsigned *thrdaddr
);

 

https://learn.microsoft.com/ko-kr/cpp/c-runtime-library/reference/beginthread-beginthreadex?view=msvc-170

 

_beginthread, _beginthreadex

자세한 정보: _beginthread, _beginthreadex

learn.microsoft.com

 

* _beginthreadex 함수는 쓰레드 소멸시 ExitThread 함수 말고 _endThreadex를 써야 한다

 

* SuspendThread 함수

 : 지정된 쓰레드를 일시 중단

DWORD SuspendThread(
  [in] HANDLE hThread
);

 

hThread

 : 일시 중단될 쓰레드에 대한 핸들

 

https://learn.microsoft.com/ko-kr/windows/win32/api/processthreadsapi/nf-processthreadsapi-suspendthread

 

SuspendThread 함수(processthreadsapi.h) - Win32 apps

지정된 스레드를 일시 중단합니다.

learn.microsoft.com

 

* ResumeThread 함수

 : 쓰레드의 일시 중단 횟수를 감소

   일시 중단 횟수가 0으로 감소하면 쓰레드의 실행이 다시 시작된다

 

https://learn.microsoft.com/ko-kr/windows/win32/api/processthreadsapi/nf-processthreadsapi-resumethread

 

ResumeThread 함수(processthreadsapi.h) - Win32 apps

스레드의 일시 중단 횟수를 감소합니다. 일시 중단 횟수가 0으로 감소하면 스레드 실행이 다시 시작됩니다.

learn.microsoft.com

 

* 프로세스는 실행의 주체가 아닌 쓰레드를 담는 그릇

   ㄴ 따라서, 프로세스 안에서 동작하는 쓰레드가 우선순위를 갖는다