임계 영역 접근 동기화
- 메모리 접근의 동기화
- 임계 영역 : 한 순간에 하나의 쓰레드만 접근이 요구되는 공유 리소스에 접근하는 코드 블록
유저 모드 동기화
- 크리티컬 섹션 기반의 동기화
-> key : 둘 이상의 쓰레드 접근을 막기 위해 열쇠를 이용한다고 생각하면 됨
-> CRITICAL_SECTION : 크리티컬 섹션 기반의 동기화에서의 키
void InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
-> InitializeCriticalSection()
* 열쇠 생성 후 초기화. 임계 영역 접근에 관련된 것을 초기화
* 동기화 기법을 적용하기 위한 최소한의 기본 작업을 내부적으로 처리하기 위해 요청
void EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
-> EnterCriticalSection()
* 임계 영역의 시작
* 열쇠를 획득하고 임계 영역에 접근
void LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
-> LeavCriticalSection()
* 임계 영역의 끝
* 열쇠를 반환하고 임계 영역을 빠져나옴
void DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
-> DeleteCriticalSection()
* 열쇠 소멸
-> EnterCriticalSection ~ LeaveCriticalSection을 임계영역으로 결정
-> 둘 이상의 쓰레드가 함수에 접근할 때 하나의 쓰레드가 먼저 EnterCriticalSection 함수에 진입했다면 LeaveCriticalSection에 도달할 때 까지 다른 쓰레드는 blocked 상태가 됨
-> 그렇기 때문에 임계 영역의 범위는 최소한으로 해야 효율적
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <process.h>
#define NUM_OF_GATE 6
LONG gTotalCount = 0; // 둘 이상의 쓰레드가 접근하는 변수
CRITICAL_SECTION cSection;
void IncreaseCount()
{
EnterCriticalSection(&cSection); // 임계 영역 시작
gTotalCount++;
LeaveCriticalSection(&cSection); // 임계 영역 끝
}
unsigned int WINAPI ThreadProc(LPVOID lpParam)
{
for (DWORD i = 0; i < 1000; i++)
{
IncreaseCount();
}
return 0;
}
int _tmain(int argc, TCHAR* argv[])
{
DWORD dwThreadId[NUM_OF_GATE];
HANDLE hThread[NUM_OF_GATE];
InitializeCriticalSection(&cSection);
for (DWORD i = 0; i < NUM_OF_GATE; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, CREATE_SUSPENDED, (unsigned*)& dwThreadId[i]);
if (hThread[i] == NULL)
{
_tprintf(_T("Thread create error\n"));
return -1;
} // 쓰레드를 생성하지 못하면 NULL이 반환
}
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(&cSection);
return 0;
}
- 인터락 함수 기반의 동기화
-> 간편하게 임계 영역을 설정하기 위한 동기화 기법
-> 원자적 접근 보장 : 한 순간에 하나의 쓰레드에 의해서만 호출이 완료되도록 허용
LONG InterlockedIncrement(
LONG volatile *Addend
);
LONG InterlockedDecrement(
LONG volatile *Addend
);
-> InterlockedIncrement() / InterlockedDecrement()
* 전달된 변수의 값을 하나 증가 / 감소 시킴
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
#include <process.h>
#define NUM_OF_GATE 6
LONG gTotalCount = 0; // 둘 이상의 쓰레드가 접근하는 변수
void IncreaseCount()
{
// gTotalCount++;
InterlockedIncrement(&gTotalCount);
}
unsigned int WINAPI ThreadProc(LPVOID lpParam)
{
for (DWORD i = 0; i < 1000; i++)
{
IncreaseCount();
}
return 0;
}
int _tmain(int argc, TCHAR* argv[])
{
DWORD dwThreadId[NUM_OF_GATE];
HANDLE hThread[NUM_OF_GATE];
for (DWORD i = 0; i < NUM_OF_GATE; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, NULL, CREATE_SUSPENDED, (unsigned*)& dwThreadId[i]);
if (hThread[i] == NULL)
{
_tprintf(_T("Thread create error\n"));
return -1;
} // 쓰레드를 생성하지 못하면 NULL이 반환
}
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;
}
'Programming > System Programming' 카테고리의 다른 글
윈도우즈 시스템 프로그래밍 - 13. 쓰레드 동기화 기법1(4) (0) | 2020.08.05 |
---|---|
윈도우즈 시스템 프로그래밍 - 13. 쓰레드 동기화 기법1(3) (0) | 2020.08.04 |
윈도우즈 시스템 프로그래밍 - 13. 쓰레드 동기화 기법1(1) (0) | 2020.08.03 |
윈도우즈 시스템 프로그래밍 - 12. 쓰레드의 생성과 소멸(3) (0) | 2020.07.26 |
윈도우즈 시스템 프로그래밍 - 12. 쓰레드의 생성과 소멸(2) (0) | 2020.07.26 |