한 Process 는 최소 1개 이상의 Thread 를 갖는다.
Thread 는 개별화된 흐름(문맥) 과 전용 스택을 갖는 실행의 단위 이다.
모든 Thread 는 자신이 속한 Process 의 가상 메모리 공간을 공유한다.
Win32 스레드 생성 및 실행
T1 (main thread)
|
|
| - - - CreateThread() - - - > T2 (worker thread)
| |
| ← wait event | 동기화 필요함(동기화 객체 : Critical section, Event, Mutex, semaphore)
| end
worker thread 생성 및 동기화
DWORD dwThreadID = 0;
//새로운 스레드를 생성한다.
HANDLE hThread = ::CreateThread(
NULL, //보안속성 상속 (생성시키는 스레드의 보안 속성을 상속)
0, //스택 메모리는 기본크기(1MB).
ThreadFunction, //스래드로 실행할 함수이름.
NULL, //함수에 전달할 매개변수.
0, //생성 플래그는 기본값 사용.
&dwThreadID); //생성된 스레드ID 저장.
::CloseHandle(hThread); : 생성된 스레드를 닫음
예제 코드 분석
// stdafx.h : 자주 사용하지만 자주 변경되지는 않는
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
// 들어 있는 포함 파일입니다.
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: 프로그램에 필요한 추가 헤더는 여기에서 참조합니다.
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
// WorkerThreadCreate.pch는 미리 컴파일된 헤더가 됩니다.
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
#include "stdafx.h"
// TODO: 필요한 추가 헤더는
// 이 파일이 아닌 STDAFX.H에서 참조합니다.
#pragma once
// SDKDDKVer.h를 포함하면 최고 수준의 가용성을 가진 Windows 플랫폼이 정의됩니다.
// 이전 Windows 플랫폼에 대해 응용 프로그램을 빌드하려는 경우에는 SDKDDKVer.h를 포함하기 전에
// WinSDKVer.h를 포함하고 _WIN32_WINNT 매크로를 지원하려는 플랫폼으로 설정하십시오.
#include <SDKDDKVer.h>
WorkerThreadCreate.cpp
// WorkerThreadCreate.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include <Windows.h>
//_tmain() 함수와는 별도로 작동하는 작업자 스레드 함수.
DWORD WINAPI ThreadFunction(LPVOID pParam)
{
puts("*** Begin Thread ****");
for (int i = 0; i < 5; ++i)
printf("[Worker thread] %d\\n", i);
puts("**** End Thread ****");
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwThreadID = 0;
//새로운 스레드를 생성한다.
HANDLE hThread = ::CreateThread(
NULL, //보안속성 상속.
0, //스택 메모리는 기본크기(1MB).
ThreadFunction, //스래드로 실행할 함수이름.
NULL, //함수에 전달할 매개변수.
0, //생성 플래그는 기본값 사용.
&dwThreadID); //생성된 스레드ID 저장.
for (int i = 0; i < 10; ++i)
printf("[Main thread] %d\\n", i);
::CloseHandle(hThread);
//::Sleep(10);
return 0;
}
WorkerThreadSync.cpp - event 객체 중 EVENT 사용
// WorkerThreadSync.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include <Windows.h>
//작업자 스레드 함수.
DWORD WINAPI ThreadFunction(LPVOID pParam)
{
puts("*** Begin Thread ****");
for (int i = 0; i < 5; ++i)
{
printf("[Worker thread] %d\\n", i);
::Sleep(1);
}
//스레드가 끝나기 전에 이벤트를 세트한다.
puts("종료 이벤트 세트 전");
//이 함수를 호출하면 _tmain() 함수의
//WaitForSingleObject() 함수가 반환한다!
::SetEvent((HANDLE)pParam);
puts("종료 이벤트 세트 후");
puts("**** End Thread ****");
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
//이벤트 객체를 생성한다.
HANDLE hEvent = ::CreateEvent(
NULL, //디폴트 보안 속성 적용.
FALSE, //자동으로 상태 전환.
FALSE, //초기상태는 FALSE.
NULL); //이름 없음.
//작업자 스레드를 생성하고 시작한다.
DWORD dwThreadID = 0;
HANDLE hThread = ::CreateThread(NULL, 0,
ThreadFunction,
hEvent, //이벤트 핸들을 스레드 함수에 전달한다.
0, &dwThreadID);
//작업자 스레드와 동시에 실행되는 코드 영역의 시작.
for (int i = 0; i < 5; ++i)
{
printf("[Main thread] %d\\n", i);
//i값이 3이면 이벤트가 세트되기(::SetEvent)를 무한정 기다린다!
if (i == 3 &&
::WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0)
{
puts("종료 이벤트를 감지했습니다!");
::CloseHandle(hEvent);
hEvent = NULL;
}
}
::CloseHandle(hThread);
return 0;
}