34
Chapter 05. 멀멀멀멀멀

Chapter 05. 멀티스레드

Embed Size (px)

DESCRIPTION

Chapter 05. 멀티스레드. 학습 목표. 멀티스레드의 필요성을 이해하고 기본 개념을 익힌다 . 멀티스레드를 이용하여 TCP 서버를 작성한다 . 스레드 동기화 기법을 익힌다. 프로세스와 스레드 (1/2). 용어 프로세스 (process) 메모리를 비롯한 각종 리소스를 담고 있는 컨테이너 (container) 로서 정적인 개념 스레드 (thread) 실제 CPU 시간을 할당받아 수행되는 실행 단위로서 동적인 개념 주 스레드 (primary thread) - PowerPoint PPT Presentation

Citation preview

Page 1: Chapter  05. 멀티스레드

Chapter 05.

멀티스레드

Page 2: Chapter  05. 멀티스레드

- 2 -

학습 목표

• 멀티스레드의 필요성을 이해하고 기본 개념을 익힌다 .

• 멀티스레드를 이용하여 TCP 서버를 작성한다 .• 스레드 동기화 기법을 익힌다 .

Page 3: Chapter  05. 멀티스레드

- 3 -

프로세스와 스레드 (1/2)

• 용어– 프로세스 (process)

• 메모리를 비롯한 각종 리소스를 담고 있는 컨테이너 (container)로서 정적인 개념

– 스레드 (thread)• 실제 CPU 시간을 할당받아 수행되는 실행 단위로서 동적인 개념

– 주 스레드 (primary thread)• main() 또는 WinMain() 함수에서 시작되는 스레드로 ,

프로세스가 시작할 때 생성

– 컨텍스트 전환 (context switch)• CPU 와 운영체제의 협동으로 이루어지는 스레드 실행 상태의

저장과 복원 작업

Page 4: Chapter  05. 멀티스레드

- 4 -

프로세스와 스레드 (2/2)

• 컨텍스트 전환 과정

CPU

① ②

CPU

① ② 스레드①레지스터

스레드②레지스터

CPU

① ②

CPU

① ② 스레드①레지스터

스레드②레지스터

Page 5: Chapter  05. 멀티스레드

- 5 -

스레드 생성과 종료 (1/6)

• 스레드 생성에 필요한 요소– 스레드 함수 (thread function) 의 시작 주소– 스레드 함수 실행시 사용할 스택 영역의 크기

Page 6: Chapter  05. 멀티스레드

- 6 -

스레드 생성과 종료 (2/6)

• 프로세스의 주소 공간– 두 개의 함수– 세 개의 스레드

f(){ ...}main(){ ...}

주 스레드의실행 스택

스레드 ①의실행 스택

코드

스레드 ②의실행 스택

주 스레드

스레드 ① , ②

Page 7: Chapter  05. 멀티스레드

- 7 -

스레드 생성과 종료 (3/6)

• CreateThread() 함수– 스레드를 생성한 후 스레드 핸들 (thread handle) 을 리턴

HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, // NULL SIZE_T dwStackSize, // 0 LPTHREAD_START_ROUTINE lpStartAddress, // 스레드 함수 LPVOID lpParameter, // 스레드 함수 인자 DWORD dwCreationFlags, // 0 또는 CREATE_SUSPENDED LPDWORD lpThreadId // 스레드 ID) ; 성공 : 스레드 핸들 , 실패 : NULL

Page 8: Chapter  05. 멀티스레드

- 8 -

스레드 생성과 종료 (4/6)

• 스레드 함수 정의

DWORD WINAPI ThreadProc (LPVOID lpParameter){ ...}

Page 9: Chapter  05. 멀티스레드

- 9 -

스레드 생성과 종료 (5/6)

• 스레드 종료 방법① 스레드 함수가 리턴② 스레드 함수 내에서 ExitThread() 함수를 호출③ TerminateThread() 함수를 호출④ 주 스레드가 종료하면 모든 스레드가 종료

Page 10: Chapter  05. 멀티스레드

- 10 -

스레드 생성과 종료 (6/6)

• 스레드 종료 함수

void ExitThread ( DWORD dwExitCode // 종료 코드) ;

BOOL TerminateThread ( HANDLE hThread, // 종료할 스레드를 가리키는 핸들 DWORD dwExitCode // 종료 코드) ; 성공 : 0 이 아닌 값 , 실패 : 0

Page 11: Chapter  05. 멀티스레드

- 11 -

스레드 조작 – 우선 순위 (1/5)

• 용어– 스레드 스케줄링 (thread scheduling)

• 윈도우가 각 스레드에게 CPU 시간을 적절히 분배하기 위한 정책

– 우선순위 클래스 (priority class)• 프로세스 속성으로 , 한 프로세스가 생성한 스레드는 모두 동일한

우선순위 클래스를 가짐

– 우선순위 레벨 (priority level)• 스레드 속성으로 , 한 프로세스에 속한 스레드 사이에서 상대적인

우선순위를 결정할 때 사용

– 기초 우선순위 (base priority)• 우선순위 클래스와 우선순위 레벨을 결합한 값으로 , 스레드

스케줄링에 사용

Page 12: Chapter  05. 멀티스레드

- 12 -

스레드 조작 – 우선 순위 (2/5)

• 우선 순위 클래스– REALTIME_PRIORITY_CLASS( 실시간 )– HIGH_PRIORITY_CLASS( 높음 )– ABOVE_NORMAL_PRIORITY_CLASS( 보통 초과 ; 윈도우 2

000/XP/2003)– NORMAL_PRIORITY_CLASS( 보통 )– BELOW_NORMAL_PRIORITY_CLASS( 보통 미만 ; 윈도우 2

000/XP/2003)– IDLE_PRIORITY_CLASS( 낮음 )

Page 13: Chapter  05. 멀티스레드

- 13 -

스레드 조작 – 우선 순위 (3/5)

• 우선 순위 레벨– THREAD_PRIORITY_TIME_CRITICAL– THREAD_PRIORITY_HIGHEST– THREAD_PRIORITY_ABOVE_NORMAL– THREAD_PRIORITY_NORMAL– THREAD_PRIORITY_BELOW_NORMAL– THREAD_PRIORITY_LOWEST– THREAD_PRIORITY_IDLE

Page 14: Chapter  05. 멀티스레드

- 14 -

스레드 조작 – 우선 순위 (4/5)

• 우선 순위 기반 스레드 스케줄링

...

스케줄러

CPU

스레드

( 낮음 ) 기초 우선순위 ( 높음 )

세 개의 스레드를교대로 수행

Page 15: Chapter  05. 멀티스레드

- 15 -

스레드 조작 – 우선 순위 (5/5)

• 우선 순위 레벨 조작 함수

BOOL SetThreadPriority ( HANDLE hThread, // 스레드 핸들 int nPriority // 우선순위 레벨값) ; 성공 : 0 이 아닌 값 , 실패 : 0

int GetThreadPriority ( HANDLE hThread // 스레드 핸들) ; 성공 : 우선순위 레벨값 , 실패 : THREAD_PRIORITY_ERROR_RETURN

Page 16: Chapter  05. 멀티스레드

- 16 -

스레드 조작 – 스레드 종료 대기 (1/4)

• WaitForSingleObject() 함수– 특정 스레드가 종료할 때까지 대기

• WaitForSingleObject() 함수 사용 예

DWORD WaitForSingleObject ( HANDLE hHandle, DWORD dwMilliseconds) ; 성공 : WAIT_OBJECT_0 또는 WAIT_TIMEOUT, 실패 : WAIT_FAILED

HANDLE hThread = CreateThread(...);WaitForSingleObject(hThread, INFINITE);

Page 17: Chapter  05. 멀티스레드

- 17 -

스레드 조작 – 스레드 종료 대기 (2/4)

• WaitForMultipleObjects() 함수– 두 개 이상의 스레드가 종료할 때까지 대기

DWORD WaitForMultipleObjects ( DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds) ; 성공 : WAIT_OBJECT_0 ~ WAIT_OBJECT_0 + nCount-1 또는 WAIT_TIMEOUT, 실패 : WAIT_FAILED

Page 18: Chapter  05. 멀티스레드

- 18 -

스레드 조작 – 스레드 종료 대기 (3/4)

• WaitForMultipleObjects() 함수 사용 예 ①

// 모든 스레드 종료를 기다릴 경우HANDLE hThread[2];HANDLE hThread[0] = CreateThread(...);HANDLE hThread[1] = CreateThread(...);WaitForMultipleObjects(2, hThread, TRUE, INFINITE);

Page 19: Chapter  05. 멀티스레드

- 19 -

스레드 조작 – 스레드 종료 대기 (4/4)

• WaitForMultipleObjects() 함수 사용 예 ②

// 두 스레드 중 하나의 종료를 기다릴 경우HANDLE hThread[2];HANDLE hThread[0] = CreateThread(...);HANDLE hThread[1] = CreateThread(...);DWORD retval = WaitForMultipleObjects(2, hThread, FALSE, INFINITE);switch(retval){case WAIT_OBJECT_0: // hThread[0] 종료 break;case WAIT_OBJECT_0+1: // hThread[1] 종료 break;case WAIT_FAILED: // 오류 발생 break;}

Page 20: Chapter  05. 멀티스레드

- 20 -

스레드 조작 – 실행 중지와 재실행 (1/2)

• 실행 중지 함수 ①

• 재실행 함수

DWORD SuspendThread ( HANDLE hThread // 스레드 핸들) ; 성공 : 중지 횟수 , 실패 : -1

DWORD ResumeThread ( HANDLE hThread // 스레드 핸들) ; 성공 : 중지 횟수 , 실패 : -1

Page 21: Chapter  05. 멀티스레드

- 21 -

스레드 조작 – 실행 중지와 재실행 (2/2)

• 실행 중지 함수 ②– 스레드가 실행을 멈추고 일정 시간동안 대기

void Sleep ( DWORD dwMilliseconds // 밀리초 (ms)) ;

Page 22: Chapter  05. 멀티스레드

- 22 -

멀티스레드 TCP 서버 (1/3)

• 기본 구조

DWORD WINAPI ProcessClient(LPVOID arg){ // 전달된 소켓 ③ SOCKET client_sock = (SOCKET)arg;

// 클라이언트 정보 얻기 ④ addrlen = sizeof(clientaddr); getpeername(client_sock, (SOCKADDR *)&clientaddr, &addrlen);

// 클라이언트와 데이터 통신 ⑤ while(1){ ... }

closesocket(client_sock); return 0;}

Page 23: Chapter  05. 멀티스레드

- 23 -

멀티스레드 TCP 서버 (2/3)

• 기본 구조 (cont’d)

int main(int argc, char* argv[]){ ... while(1){ // 클라이언트 접속 수용 ① client_sock = accept(listen_sock, ...); ... // 스레드 생성 ② CreateThread(NULL, 0, ProcessClient, (LPVOID)client_sock, 0, &ThreadId); } ...}

Page 24: Chapter  05. 멀티스레드

- 24 -

멀티스레드 TCP 서버 (3/3)

• 소켓과 연관된 주소 정보 얻기

int getpeername ( SOCKET s, struct sockaddr* name, int* namelen) ; 성공 : 0, 실패 : SOCKET_ERROR

int getsockname ( SOCKET s, struct sockaddr* name, int* namelen) ; 성공 : 0, 실패 : SOCKET_ERROR

Page 25: Chapter  05. 멀티스레드

- 25 -

스레드 동기화 (1/4)

• 스레드 동기화 (thread synchronization) 필요성– 멀티스레드를 사용하는 프로그램에서 두 개 이상의

스레드가 공유 데이터를 접근하는 경우

스레드 1

int money = 1000

...

① read money into ECX

② ECX = ECX + 2000

③ write ECX into money

...

스레드 2...

① read money into ECX

② ECX = ECX + 4000

③ write ECX into money

...

공유 변수

Page 26: Chapter  05. 멀티스레드

- 26 -

스레드 동기화 (2/4)

• 다양한 스레드 동기화 기법종류 주요 용도임계영역(critical section)

공유 리소스에 대해 오직 하나의 스레드 접근만 허용( 한 프로세스에 속한 스레드에만 사용 가능 )

뮤텍스(mutex)

공유 리소스에 대해 오직 하나의 스레드 접근만 허용( 서로 다른 프로세스에 속한 스레드에도 사용 가능 )

이벤트(event)

특정 사건 발생을 다른 스레드에게 알림

세마포(semaphore)

한정된 개수의 자원을 여러 스레드가 사용하려고 할 때 , 접근을 제한

대기 가능 타이머(waitable timer)

특정 시간이 되면 대기 중인 스레드를 깨움

Page 27: Chapter  05. 멀티스레드

- 27 -

스레드 동기화 (3/4)

• 스레드 동기화 원리

스레드 1 매개체 스레드 2

진행 대기

Page 28: Chapter  05. 멀티스레드

- 28 -

스레드 동기화 (4/4)

• 스레드 동기화 원리 (cont’d)

동기화 객체 동기화 객체

비신호 상태 신호 상태

Wait*() 함수로 감지

Page 29: Chapter  05. 멀티스레드

- 29 -

임계 영역 (1/3)

• 임계 영역 (critical section)– 두 개 이상의 스레드가 공유 리소스를 접근할 때 , 오직

하나의 스레드 접근만 허용해야 하는 경우에 사용

• 특징– 유저 (user) 영역 메모리에 존재하는 구조체이므로 한

프로세스에 속한 스레드 동기화에만 사용 가능– 일반적인 동기화 객체보다 빠르고 효율적

Page 30: Chapter  05. 멀티스레드

- 30 -

임계 영역 (2/3)

• 임계 영역 사용 예

#include <windows.h>

CRITICAL_SECTION cs; // ①

// 스레드 1DWORD WINAPI Thread1(LPVOID arg){ ... EnterCriticalSection(&cs); // ③ // 공유 리소스 접근 LeaveCriticalSection(&cs); // ④ ...}

Page 31: Chapter  05. 멀티스레드

- 31 -

임계 영역 (3/3)

• 임계 영역 사용 예 (cont’d)// 스레드 2DWORD WINAPI Thread2(LPVOID arg){ ... EnterCriticalSection(&cs); // ③ // 공유 리소스 접근 LeaveCriticalSection(&cs); // ④ ...}

int main(){ ... InitializeCriticalSection(&cs); // ② // 스레드 생성과 종료 DeleteCriticalSection(&cs); // ⑤ ...}

Page 32: Chapter  05. 멀티스레드

- 32 -

이벤트 객체 (1/3)

• 이벤트 객체 (event object)– 특정 사건 발생을 다른 스레드에게 알릴 때 주로 사용

• 이벤트 객체를 이용한 동기화 예① 이벤트 객체를 비신호 상태로 생성② 한 스레드가 작업을 진행하고 , 나머지 스레드는 이벤트

객체에 대해 Wait*() 함수를 호출함으로써 이벤트 객체가 신호 상태가 되기를 기다림

③ 스레드가 작업을 완료하면 , 이벤트를 신호 상태로 바꿈④ 기다리고 있던 모든 스레드가 깨어나서 작업을 진행

Page 33: Chapter  05. 멀티스레드

- 33 -

이벤트 객체 (2/3)

• 이벤트 객체 상태 변경

• 이벤트 객체의 종류– 자동 리셋 (auto-reset) 이벤트– 수동 리셋 (manual-reset) 이벤트

BOOL SetEvent (HANDLE hEvent) ; // 비신호 상태 신호 상태BOOL ResetEvent (HANDLE hEvent) ; // 신호 상태 비신호 상태

Page 34: Chapter  05. 멀티스레드

- 34 -

이벤트 객체 (3/3)

• 이벤트 객체 생성

HANDLE CreateEvent ( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName) ; 성공 : 이벤트 핸들 , 실패 : NULL