쓰레드 생성 :
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // 보안속성(TRUE : 상속, NULL : 상속제외)
SIZE_T dwStackSize, // 쓰레드의 스택 크기
LPTHREAD_START_ROUTINE lpStartAddress, // 쓰레드로 동작하기 위한 함수(쓰레드 main)
// 리턴타입 DWORD, 매개변수 타입 LPVOID(void*)
LPVOID lpParameter, // 쓰레드 함수에 전달할 인자 지정
DWORD dwCreationFlags, // 쓰레드 생성 및 실행을 조절
LPDWORD lpThreadId // 쓰레드 ID를 전달받기 위한 변수의 주소값
);
쓰레드 소멸 :
1. return(일반적, 안정적) :
쓰레드 함수에서 return 은 쓰레드 종료
main 쓰레드의 return 은 프로세스 종료
쓰레드 함수의 return 값은 그 쓰레드의 커널 오브젝트에 저장된다.
리턴값 획득 :
BOOL GetExitCodeThread(
HANDLE hThread, // 종료코드를 얻기 위한 쓰레드의 핸들
LPDWORD lpExitCode // 얻게 되는 종료코드를 저장할 메모리 주소
);
2. ExitThread(특정 위치에서 쓰레드의 실행을 종료) :
현재 실행 중인 쓰레드를 종료
VOID ExitThread(
DWORD dwExitCode // 커널 오브젝트에 등록되는 쓰레드 종료 코드를 지정
); // GetExitCodeThread 함수를 통해 종료코드 획득 가능
이 함수를 사용하면 언제 어디서나 쓰레드를 종료 시킬수 있다.
(참고 : C++ 프로그래밍을 할때 주의해야 한다.
예를 들어 A, B 함수에 C++ 객체가 존재한다고 할때 C 함수에서 ExitThread 함수로 쓰레드를 종료할 경우
A, B 함수의 스택 프레임에 존재하는 소멸자가 호출되지 않아 메모리 유출 현상이 발생할 수도 있다.
return 문에 의한 쓰레드 종료가 가장 좋다)
3. TerminateThread(외부에서 쓰레드를 종료) :
강제종료 함수
따라서 종료에 필요한 여러 가지 일들을 처리하지 못하고 바로 종료된다.
BOOL TerminateThread(
HANDLE hThread, // 강제 종료할 쓰레드의 핸들
DWORD dwExitCode // 종료할 쓰레드의 종료코드를 인자로 전달
);
4. 프로세스로부터 쓰레드 분리
쓰레드는 생성과 동시에 프로세스의 핸들 테이블에 그 핸들이 등록되므로 Usage Count 가 2가 된다.
따라서 쓰레드 생성시 얻은 핸들을 CloseHandle 로 반환하면 Usage Count = 1 이 된다.
쓰레드를 종료하면 Usage Count = 0 이 되어 쓰레드 커널 오브젝트가 소멸된다.
쓰레드의 성격과 특성 :
공유 영역 사용 :
ex)
total 을 전역변수로 선언했다. 따라서 모든 쓰레드는 공유 total 을 가지고 덧셈연산을 진행한다.
최종결과를 main 쓰레드가 참조한다.
동시접근의 문제점 :
위 ex) 에서 둘 이상의 쓰레드가 전역변수 total 에 동시접근할 경우 문제점이 생긴다.
컨텍스트 스위칭은 연중에도 빈번히 일어날 수 있기에 둘 이상의 쓰레드가 같은 메모리 영역을 동시에 참조하는 것은 문제를 발생시킨다.
따라서 멀티 쓰레드 기반의 쓰레드를 생성해야 한다.
uintptr_t _beginthreadex( // CreateThread 함수와 파라미터 순서와 의미가 같다.(자료형과 리턴형의 차이가 있다)
void *security,
unsigned stack_size,
unsigned (*start_address)(void *),
void *arglist,
unsigned initflag,
unsigned *thrdaddr
);
_beginthreadex 함수를 사용하면
쓰레드 함수에 여러 파라미터를 전달할 수 있다.
각각의 쓰레드를 위해서 독립적인 메모리 블록을 할당한다.
(스택 공간 + 고유한 레지스터 값 + 현재 명령 주소) // CreatThread 함수 (스택 공간)
따라서 return 과 endthreadex 함수를 사용하여 할당한 메모리를 해제해야 한다.
void _endthreadex(unsigned retval); // ExitThread 함수와 동일
쓰레드의 상태 컨트롤 :
쓰레드의 상태 변화(Suspend & Resume) : // 프로세스 상태 변화와 개념이 같다.
// http://dakuo.tistory.com/entry/프로세스의-생성과-소멸
쓰레드의 커널 오브젝트 멤버 Suspend Count 는 쓰레드의 상태를 나타낸다.
Suspend Count = 0 : 현재 실행중인 쓰레드(Ready)
Suspend Count > 0 : Block 상태
DWORD SuspendThread(
HANDLE hThread // Suspend Count++ 할 쓰레드의 핸들
);
DWORD ResumeThread(
HANDLE hThread // Suspend Count-- 할 쓰레드의 핸들
);
이 함수들은 변경되기 이전에 Suspend Count 를 리턴한다.
쓰레드의 우선순위 컨트롤 :
프로세스의 우선순위는 기존 우선순위라고 표현한다.
쓰레드는 추가로 상대적 우선순위를 갖는다.
Priority | 의미 |
THREAD_PRIORITY_LOWEST | -2 |
THREAD_PRIORITY_BELOW_NORMAL | -1 |
THREAD_PRIORITY_NORMAL | 0 (Default) |
THREAD_PRIORITY_ABOVE_NORMAL | +1 |
THREAD_PRIORITY_HIGHEST | +2 |
예)
NORMAL_PRIORITY_CLASS (기존 우선순위 9) + THREAD_PRIORITY_LOWEST(-2) = 7
즉, 이 쓰레드의 최종우선순위는 7이다
쓰레드의 상대적 우선순위 변경 :
BOOL SetThreadPriority(
HANDLE hThread, // 우선순위를 변경할 쓰레드의 핸들
int nPriority // 우선순위 상수값
);
int GetThreadPriority(
HANDLE hThread // 우선순위를 확인할 쓰레드의 핸들
);
'Windows > _System Programming' 카테고리의 다른 글
쓰레드(Thread) 실행순서 동기화 (0) | 2010.03.04 |
---|---|
쓰레드(Thread) 메모리 접근 동기화 (0) | 2010.03.04 |
쓰레드(Thread) (2) | 2010.02.28 |
환경변수 (0) | 2010.02.25 |
스케줄링 알고리즘과 우선순위 (0) | 2010.02.25 |