삽질의 현장/- 윈도우 시스템

#019_WIndow_System_쓰레드(thread) 제어

shovelman 2015. 9. 22. 13:15


안녕하세요 삽잡이입니다.

이번시간에는 지난 시간에 이어서 쓰레드에 대해 알아보려고합니다.


이전 시간까지 쓰레드를 생성할 때에는 CreateThread() 함수를 실행했습니다.



그런데 이 CreateThread 함수는 API에서 제공하는 함수입니다.


Thread를 띄우는 함수에는 위의 함수 외에 _beginthread()함수가 있습니다.

둘이 차이는 없지만, 

일반적으로 _beginthread()함수를 더 많이 사용한다고 합니다. (믿거나 말거나)


CreateThread는 다시 말하지만, API함수입니다.

thread는 stack을 제외한 Global Data 영역과 heap 영역을 공유합니다.

즉, thread는 static 변수의 내용을 공유한다는 것입니다.

그런데 C언어의 런타임 라이브러리를 사용할 때 문제가 발생하게 됩니다.


런타임 라이브러리란, 

쉽게 '실행 중에 로딩하여 사용하는 라이브러리'를 말합니다.

위키백과에서는 '컴퓨터 프로그램을 실행하는 동안 프로그래밍 언어로 기능을 추가하기 위해

컴파일러가 사용하는 특별한 프로그램 라이브러리'라고 정의하군요...


아무튼... 이와 같은 런타임 라이브러리에는

malloc(), rand(), srand(), gets() 등의 함수들이 있습니다.

그런데 이놈들 안에는 static 변수가 있다는 것이 문제입니다.

예를 들어 srand()의 초기값을 보고 rand() 함수가 호출할 때마다 랜덤 수가 결정되는데 

그 이유는 static 변수로 보관하고 있기 때문입니다.


흠... 그래도 왜 문제인지 의문이 드신다면...

지난 시간에 static 변수를 쓰레드 내에서 사용할 때 신경 써야한다는 말을 한 적이 있는데요...

thread는 static 변수에 내용을 공유합니다.

그렇다면, 우리는 TLS로 변수를 바꿔줄 필요성이 있습니다.

그런 역할을 해주는 쓰레드가 _beginthread() 함수 입니다.


_beginthread 함수는 두 가지 종류가 있습니다.

기본적인 _beginthread와 _beginthreadex 이 두가지 말입니다.

후자 함수의 경우 CreateThread와 똑같다고 보시면 됩니다...

왜냐, 인자가 CreateThread 함수와 같이 때문입니다.

따라서 CreateThread 함수를 쓰는 곳에는 _beginthreadex로 바꿔 쓸 수 있다는 것이지요...


어떻게 생겨먹은 놈인지 살펴보고 가시겠습니다.

우선, 이놈들은 API함수가 아니기 떄문에 process.h 헤더 포함되어 있습니다.




이렇게 생겨먹었습니다.

아무튼, _beginthread 함수에도 내부적으로 CreateThread 함수를 사용합니다.

그런데 런타임 함수에 static 변수를 TLS로 바꿔준다는 것입니다.


_beginthreadex() 함수의 경우 CreateThread() 함수와 인수는 똑같은데,

반환 타입이 주소 형식이라는 차이점이 있습니다.

그런데, 어차피 핸들도 주소형식이니 핸들을 받고싶다면 타입 변환만 해주면 됩니다.


또, unsigned int 형을 반환한다는 특징이 있습니다.

왜냐하면 이 함수는 API 함수가 아니기 때문에 핸들같은 것이 없지 않겠습니까...

아무튼... 함수는 똑같다는 거~


자... 이제 본격적으로 쓰레드 제어에 대해서 알아보도록 하겠습니다.


쓰레드를 제어하기 위해서는

SuspendThread(), ResumeThread(), TerminateThread() 함수 등이 준비되어 있습니다.

물론, 마지막 함수는 누누히 말하지만 그리 권장하는 함수는 아닙니다.


우선, SuspendThread() 함수에 대해서 살펴보겠습니다.

이처럼 생겨먹은 요놈은, 쓰레드의 실행을 멈추는 기능을 가지고 있습니다.

즉, Sleep 상태에 놓이게 하는 것입니다.

다른 말로 상태를 Blocking 상태로 만들게 하는 것입니다.

그렇게 되면, Ready 상태로 만들지 못해서 Running 상태로 가지 못합니다...


예를 들어서 네트워크에서 어떠한 파일을 다운 받고 있다고 해봅시다.

다운로드를 일시 정지 할 때에도 동작을 하고 있으면 문제가 생기겠지요...

이럴 때 해당 함수를 사용합니다.


ResumeThread() 함수는 멈춰있던 쓰레드를 재개하는 기능을 가지고 있습니다.



마지막으로, 별로 권장하지 않는 함수...



너무 미워해서 미안하지만...

이 함수는 쓰레드가 할당한 메모리, 리소스를 마무리 하지 않고 죽여버리기 때문에,

별로 좋은 함수는 아닙니다...


그렇다면, 정상적으로 종료하는 것은 뭘까요?

쓰레드가 스스로 종료할 수 있도록 만드는 것입니다.

흠... 어떻게 하면 쓰레드가 스스로 종료할 수 있도록 잘 만들 수 있을까요...

쓰레드의 실행 상태도 관리하는 변수를 생성하는 것도 좋은 방법이겠군요...

실행 상태를 관리하는 변수를 생성하여, 

thread가 알아서 종료 되도록 만드는 것입니다.

즉, 자기 자신이 동작할지 안할지에 대해 수행할 수 있게되겠군요...


정상적으로 종료하는 쓰레드는 어떻게 구현할지

한번 생각해보도록 해야겠네요...


오늘은 여기까지...

이상 삽잡이였습니다!