visual c++ programming multithread

36
Visual C++ Programming MultiThread Department of Digital Contents Sang Il Park

Upload: rebekah-joyner

Post on 30-Dec-2015

97 views

Category:

Documents


0 download

DESCRIPTION

Visual C++ Programming MultiThread. Department of Digital Contents Sang Il Park. Multi-Threading. 개요. 멀티태스킹과 멀티스레딩 멀티태스킹 하나의 CPU 가 여러 개의 프로세스를 교대로 수행 멀티스레딩 하나의 CPU 가 여러 개의 스레드를 교대로 수행 멀티스레딩의 중요성 응용 프로그램이 직접 스레드 생성과 파괴를 관리 스레드 사용 여부에 따라 응용 프로그램의 성능 차이가 생기므로 중요한 프로그래밍 요소임. MFC 스레드. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Visual C++ Programming MultiThread

Visual C++ ProgrammingMultiThread

Department of Digital Contents

Sang Il Park

Page 2: Visual C++ Programming MultiThread

Multi-Threading

Page 3: Visual C++ Programming MultiThread

3

개요

• 멀티태스킹과 멀티스레딩– 멀티태스킹

• 하나의 CPU 가 여러 개의 프로세스를 교대로 수행

– 멀티스레딩• 하나의 CPU 가 여러 개의 스레드를 교대로 수행

• 멀티스레딩의 중요성– 응용 프로그램이 직접 스레드 생성과 파괴를 관리– 스레드 사용 여부에 따라 응용 프로그램의 성능 차이가

생기므로 중요한 프로그래밍 요소임

Page 4: Visual C++ Programming MultiThread

4

MFC 스레드

• MFC 스레드 종류– 작업자 스레드

• 메시지 루프를 가지고 있지 않다 .

– 사용자 인터페이스 스레드 (UI 스레드 )• 메시지 루프를 가지고 있다 .

Page 5: Visual C++ Programming MultiThread

작업자 스레드 사용하기 :

• 1. 작업을 수행할 전역함수 선언

• 2. 전역함수를 AfxBeginThread 를 통해 호출

UINT DoIt( LPVOID value ){ …}

UINT DoIt( LPVOID value ){ …}

AfxBeginThread(DoIt, (LPVOID) value);AfxBeginThread(DoIt, (LPVOID) value);

UINT:Unsigned IntegerLPVOID: 32bit 크기를 가지는 임의의 변수형 (ex. 정수 , pointer)

UINT:Unsigned IntegerLPVOID: 32bit 크기를 가지는 임의의 변수형 (ex. 정수 , pointer)

Page 6: Visual C++ Programming MultiThread

6

작업자 스레드 (2/5)

• 스레드 생성 (cont'd)– pfnThreadProc: 스레드 실행 시작점이 되는 함수 (= 제어

함수 ) 의 주소• 제어 함수의 형태 UINT 함수이름 (LPVOID pParam);

– pParam: 제어 함수에 전달할 인자 (32 비트 ) – nPriority: 스레드의 우선순위 레벨 – nStackSize: 스레드 스택의 크기– dwCreateFlags: 0 또는 CREATE_SUSPENDED– lpSecurityAttrs: 보안 설명자와 핸들 상속 정보

CWinThread* AfxBeginThread ( pfnThreadProc, pParam, nPriority, nStackSize,

dwCreateFlags, lpSecurityAttrs );

Page 7: Visual C++ Programming MultiThread

7

작업자 스레드 (3/5)

• 스레드 제어

– 스레드 우선순위 레벨 값을 얻음

– 스레드 우선순위 레벨 값을 변경

– 스레드 실행을 일시 정지

– 스레드를 재시작

int CWinThread::GetThreadPriority ();

BOOL CWinThread::SetThreadPriority (int nPriority);

DWORD CWinThread::SuspendThread ();

DWORD CWinThread::ResumeThread ();

Page 8: Visual C++ Programming MultiThread

8

작업자 스레드 (4/5)

• 스레드 종료– 방법 1: 스레드 제어 함수가 리턴 . 리턴값이 0 이면

일반적으로 정상 종료를 뜻함– 방법 2: 스레드 제어 함수 내에서 AfxEndThread()

호출

Page 9: Visual C++ Programming MultiThread

9

작업자 스레드 (5/5)

• 스레드 종료 (cont'd)

– nExitCode: 스레드 종료 코드– bDelete: 스레드 객체를 메모리에서 제거할 것인지를

나타냄 . FALSE 를 사용하면 스레드 객체 재사용 가능

void AFXAPI AfxEndThread( UINT nExitCode, BOOL bDelete = TRUE);

Page 10: Visual C++ Programming MultiThread

코딩연습

• 왼쪽 마우스를 클릭하면 왼쪽에서 오른쪽으로 빨간 막대를 증가시키는 프로그램을 만들어라 .

Page 11: Visual C++ Programming MultiThread

11

UI 스레드 (1/4)

• UI 스레드 생성 과정– CWinThread 클래스로부터 새로운 클래스를 파생– 클래스 선언부와 구현부에 각각

DECLARE_DYNCREATE, IMPLEMENT_DYNCREATE 매크로 선언 .

– CWinThread 클래스가 제공하는 가상 함수 중 일부를 재정의 . CWinThread::InitInstance() 는 반드시 재정의해야 하며 , 나머지 함수는 필요에 따라 재정의함 .

– AfxBeginThread() 를 이용하여 새로운 UI 스레드 생성

Page 12: Visual C++ Programming MultiThread

12

UI 스레드 (2/4)

• 스레드 생성

CWinThread 타입 객체를 동적으로 생성하고 ( 스레드 를 만든 후 ) 이 객체의 주소값을 리턴

CWinThread* AfxBeginThread ( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL);

Page 13: Visual C++ Programming MultiThread

13

UI 스레드 (3/4)

• 스레드 생성 (cont'd)– pThreadClass: 객체 정보를 담고 있는

CRuntimeClass 구조체의 주소• 사용 형태 RUNTIME_CLASS( 클래스이름 )

– nPriority: 스레드의 우선순위 레벨 – nStackSize: 스레드 스택의 크기– dwCreateFlags: 0 또는 CREATE_SUSPENDED– lpSecurityAttrs: 보안 설명자와 핸들 상속 정보

Page 14: Visual C++ Programming MultiThread

14

UI 스레드 (4/4)

• 스레드 종료– 방법 1: WM_QUIT 메시지를 받아서 메시지 루프가

종료– 방법 2: 스레드 제어 함수 내에서 AfxEndThread()

호출

Page 15: Visual C++ Programming MultiThread

15

스레드 동기화 (1/3)

• MFC 클래스 계층도

Page 16: Visual C++ Programming MultiThread

16

스레드 동기화 (2/3)

• 클래스 요약 :– CSyncObject

• 스레드 동기화 클래스를 위한 공통의 인터페이스 제공

– CCriticalSection, CEvent, CMutex, CSemaphore• 윈도우 운영체제에서 제공하는 스레드 동기화 객체 ( 임계 영역 ,

이벤트 , 뮤텍스 , 세마포 ) 를 편리하고 일관성 있게 사용할 수 있도록 만든 클래스

– CSingleLock, CMultiLock• 스레드 동기화 클래스를 편리하게 사용할 수 있도록 보조

사용하기 위해서는 afxmt.h 에 가 필요사용하기 위해서는 afxmt.h 에 가 필요

Page 17: Visual C++ Programming MultiThread

17

스레드 동기화 (3/3)

• 스레드 동기화가 필요한 상황– 두 개 이상의 스레드가 공유 리소스를 사용하는 경우– 하나의 스레드가 작업을 완료한 후 , 기다리고 있던 다른

모든 스레드에게 알려주는 경우

• 스레드 동기화 원리

스레드 1 매개체 스레드 2

진행 대기

Page 18: Visual C++ Programming MultiThread

18

Critical Section(1/2)

• 용도– 같은 프로세스에 속한 스레드 간의 동기화

• 공유 리소스를 접근하는 다수의 스레드가 있을 때 오직 하나의 스레드만 접근할 수 있도록 함

• 장점– 속도가 빠름

• 단점– 서로 다른 프로세스에 속한 스레드 간의 동기화를 위한

목적으로는 사용할 수 없음

Page 19: Visual C++ Programming MultiThread

19

Critical Section(2/2)

• 사용 예

// 전역 변수로 선언CCriticalSection g_cs;...// 스레드 1g_cs.Lock();// 공유 변수 접근g_cs.Unlock();...// 스레드 2g_cs.Lock();// 공유 변수 접근g_cs.Unlock();

Page 20: Visual C++ Programming MultiThread

20

Mutex (1/3)

• 용도– 공유 리소스를 접근하는 다수의 스레드가 있을 때 오직

하나의 스레드만 접근할 수 있도록 함

• 장점– 서로 다른 프로세스에 속한 스레드 간의 동기화를 위한

목적으로는 사용할 수 있음

• 단점– 임계 영역보다 속도가 느림

Page 21: Visual C++ Programming MultiThread

21

Mutex(2/3)

• 뮤텍스 생성

– bInitiallyOwn: TRUE 면 뮤텍스를 생성한 스레드가 소유자가 됨

– lpszName: 뮤텍스 이름– lpsaAttribute: 보안 설명자와 핸들 상속 관련 구조체

CMutex::CMutex ( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL);

Page 22: Visual C++ Programming MultiThread

22

Mutex (3/3)

• 사용 예

// 전역 변수로 선언CMutex g_mutex(FALSE, NULL);...// 스레드 1g_cs.Lock();// 공유 변수 접근g_cs.Unlock();...// 스레드 2g_cs.Lock();// 공유 변수 접근g_cs.Unlock();

Page 23: Visual C++ Programming MultiThread

23

Event (1/5)

• 이벤트– 신호 (Signaled) 와 비신호 (Nonsignaled) 두 개의

상태를 가진 동기화 객체

• 용도– 두 개 이상의 스레드가 공유 리소스를 사용하는 경우

임계 영역 , 뮤텍스 , 이벤트 ( 자동 리셋 )– 하나의 스레드가 작업을 완료한 후 , 기다리고 있던 다른

모든 스레드에게 알려주는 경우 이벤트 ( 수동 리셋 )

Page 24: Visual C++ Programming MultiThread

24

Event (2/5)

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

스레드는 이벤트 객체에 대해 Lock() 을 호출함으로써 이벤트 객체가 신호 상태가 되기를 기다림

– 스레드가 초기화 작업을 완료하면 이벤트 객체를 신호 상태로 바꿈

– 기다리고 있던 모든 스레드가 깨어나서 작업을 진행

Page 25: Visual C++ Programming MultiThread

25

Event (3/5)

• 종류– 자동 리셋 (Auto Reset)

• 이벤트 객체를 신호 상태로 바꾸면 , 기다리는 스레드 중 하나만 깨운 후 자동으로 비신호 상태가 됨

– 수동 리셋 (Manual Reset)• 이벤트 객체를 신호 상태로 바꾸면 , 계속 신호 상태를 유지 .

결과적으로 기다리는 스레드를 모두 깨우게 됨 .• 리셋을 하려면 명시적으로 함수를 호출해야 함

Page 26: Visual C++ Programming MultiThread

26

Event (4/5)

• 이벤트 생성

– bInitiallyOwn: FALSE 면 비신호 , TRUE 면 신호 상태– bManualReset: FALSE 면 자동 리셋 , TRUE 면 수동

리셋– lpszName: 이벤트 이름– lpsaAttribute: 보안 설명자와 핸들 상속 관련 구조체

CEvent::CEvent ( BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL);

Page 27: Visual C++ Programming MultiThread

27

Event (5/5)

• 이벤트 상태 변경

– 이벤트 객체를 신호 상태로 바꿈

– 이벤트 객체를 비신호 상태로 바꿈

– 이벤트 객체를 신호 상태로 바꾸고 , 신호 상태를 기다리는 다른 스레드를 깨운 후 , 다시 비신호 상태로 바꿈

BOOL CEvent::SetEvent();

BOOL CEvent::ResetEvent();

BOOL CEvent::PulseEvent();

Page 28: Visual C++ Programming MultiThread

28

Semaphore (1/3)

• Semaphore– 한정된 개수의 자원을 여러 스레드가 접근하려고 할 때 ,

이를 제어하는 동기화 객체– 사용 가능한 리소스의 개수 (= 리소스 카운트 ) 를

유지하여 수행될 수 있는 스레드 개수를 조절

Page 29: Visual C++ Programming MultiThread

29

Semaphore (2/3)

• 세마포를 이용한 동기화– 세마포를 생성 . 이때 사용 가능한 자원의 개수로 리소스

카운트를 초기화– 리소스를 사용할 스레드는 자신이 필요한 리소스

개수만큼 Lock() 을 호출하며 , Lock() 이 성공할 때마다 리소스 카운트 값이 1 씩 감소 . 리소스 카운트가 0 인 상태에서 Lock() 을 호출하면 해당 스레드는 대기함 .

– 리소스 사용을 마친 스레드는 자신이 사용한 리소스 개수만큼 Unlock() 을 호출하며 , 이때마다 리소스 카운트 값이 1 씩 증가

Page 30: Visual C++ Programming MultiThread

30

Semaphore (3/3)

CSemaphore::CSemaphore ( LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName = NULL, LPSECURITY_ATTRIBUTES lpsaAttributes = NULL);

• 세마포 생성

– lInitialCount: 세마포의 초기값– lMaxCount: 세마포의 최대값– pstrName: 세마포 이름– lpsaAttribute: 보안 설명자와 핸들 상속 관련 구조체

Page 31: Visual C++ Programming MultiThread

31

CSingleLock 클래스 (1/2)

• 문제 발생 :Lock 을 하고 나서 Unlock 을 하기전 예외상황발생으로 Thread 가 종료된다면 ?

CMutex g_mutex(...);

MyThread(){ g_mutex.Lock();

// 예외 상황 발생 return

g_mutex.Unlock();}

Page 32: Visual C++ Programming MultiThread

32

CSingleLock 클래스 (1/2)

• 문제 발생 :Lock 을 하고 나서 Unlock 을 하기전 예외상황발생으로 Thread 가 종료된다면 ?

CMutex g_mutex(...);

MyThread(){ g_mutex.Lock();

// 예외 상황 발생 return

g_mutex.Unlock();}

어떤 경우든 Thread 가 종료되면 자동으로 Unlock 를 부르게 해야 한다어떤 경우든 Thread 가 종료되면 자동으로 Unlock 를 부르게 해야 한다

Page 33: Visual C++ Programming MultiThread

33

CSingleLock 클래스 (2/2)

• 해결 방법 : CSingleLock 은 소멸자가 자동으로 Unlock 을 불러줌

CMutex g_mutex(...);

MyThread(){ CSingleLock lock(&g_mutex);

lock.Lock();

// 예외 상황 발생

lock.Unlock();}

Page 34: Visual C++ Programming MultiThread

34

CMultiLock 클래스

• 여러 개의 Sync Object 를 동시에 lock 하고 싶다면 ? CMultiLock 을 사용CEvent g_event[3];CSyncObject* g_pSyncObjects[3] = { &g_event[0], &g_event[1], &g_event[2]}; MyThread(){ CMultiLock multiLock(g_pSyncObjects, 3); multiLock.Lock(); ...}

Page 35: Visual C++ Programming MultiThread

그 동안 배운 것들

• MFC 구조• MFC 로 그림 그리기 (GDI, DC)• 마우스와 키보드• 타이머• 메뉴와 툴바 /상태바• FILE Input/Output• Controls • Dialog Box• Document/View Architecture

(SDI/MDI)• Mutli-Threading

Page 36: Visual C++ Programming MultiThread

한 학기 동안 수고하셨습니다 .

기말고사 : 6 월 16 일 수업시간 /수업장소점수 ( 학점 ) 공고 : 6 월 16 일 23:59(

홈페이지 )이의신청기간 : 6 월 17 일 ~6 월 19 일

연구실로 찾아 올 것