쓰레드 동기화
유저모드 동기화
커널 모드로의 전환이 불필요하기 때문에 성능상의 이점이 있다. 다만 그만큼 기능상의 제한도 있다.
커널모드 동기화
커널에서 제공하는 동기화 기능을 활용하는 방법. 커널 모드로의 변경이 필요하고 이는 성능의 저하로 이어진다. 하지만 유저모드 동기화에서 제공하지 못하는 기능을 제공받을 수 있다.
동기화가 필요한 프로그램
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <process.h>
#define NUM_OF_GATE 6
LONG gTotalCount = 0;
void IncreaseCount()
{
++gTotalCount; // 임계영역
}
unsigned int WINAPI ThreadProc(LPVOID param)
{
for (DWORD i = 0; i < 1000; i++)
IncreaseCount();
return 0;
}
int _tmain()
{
HANDLE hThread[NUM_OF_GATE];
for (DWORD i = 0; i < NUM_OF_GATE; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, CREATE_SUSPENDED, NULL);
if (hThread[i] == NULL)
{
_tprintf(_T("Thread Creation Fail <%d> \n"), i);
return -1;
}
}
for (DWORD i = 0; i < NUM_OF_GATE; i++)
ResumeThread(hThread[i]);
WaitForMultipleObjects(NUM_OF_GATE, hThread, TRUE, INFINITE);
_tprintf(_T("total count: %d \n"), gTotalCount);
for (DWORD i = 0; i < NUM_OF_GATE; i++)
CloseHandle(hThread[i]);
return 0;
}
6개의 쓰레드가 실행된다
각각의 쓰레드에서는 전역변수 gTotalCount 를 1000번씩 증가시킨다
출력될 gTotalCount의 예상 값은 6000 이다
출력결과
나중에 이런 코드가 있다면 어떻게 디버깅을 해야할까 .. ㅎㅎ
유저 모드의 동기화
크리티컬 섹션(Critical Section) 기반의 동기화
크리티컬 섹션 = 임계영역
운영체제 교과서에서는 "상호 배제 동기화(Mutual-Exclution Synchronization)" 라고 한다
크리티컬 섹션 오브젝트
CRITICAL_SECTION gCriticalSection;
초기화
void InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
사용
void EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
반환
void LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
리소스 해제
void DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
임계영역 접근 동기화 기법 적용
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <process.h>
#define NUM_OF_GATE 6
LONG gTotalCount = 0;
CRITICAL_SECTION gCriticalSection;
void IncreaseCount()
{
EnterCriticalSection(&gCriticalSection);
++gTotalCount; // 임계영역
LeaveCriticalSection(&gCriticalSection);
}
unsigned int WINAPI ThreadProc(LPVOID param)
{
for (DWORD i = 0; i < 1000; i++)
IncreaseCount();
return 0;
}
int _tmain()
{
HANDLE hThread[NUM_OF_GATE];
InitializeCriticalSection(&gCriticalSection);
for (DWORD i = 0; i < NUM_OF_GATE; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, CREATE_SUSPENDED, NULL);
if (hThread[i] == NULL)
{
_tprintf(_T("Thread Creation Fail <%d> \n"), i);
return -1;
}
}
for (DWORD i = 0; i < NUM_OF_GATE; i++)
ResumeThread(hThread[i]);
WaitForMultipleObjects(NUM_OF_GATE, hThread, TRUE, INFINITE);
_tprintf(_T("total count: %d \n"), gTotalCount);
for (DWORD i = 0; i < NUM_OF_GATE; i++)
CloseHandle(hThread[i]);
DeleteCriticalSection(&gCriticalSection);
return 0;
}
출력결과
여러번 다시 실행해도 6000이 출력된다
'공부' 카테고리의 다른 글
VirtualAlloc 함수를 이용한 Dynamic Array Design (0) | 2020.08.15 |
---|---|
쓰레드 동기화 인터락 함수 (0) | 2020.08.06 |
컨텍스트 스위칭 (Context Switching) (0) | 2020.08.04 |
프로세스 상태변화 (0) | 2020.08.04 |
비트맵 이미지블렌딩 프로그램 만들기 (c++ 연습) (0) | 2020.07.18 |