유저 모드와 커널 모드
- 유저 모드
-> 응용 프로그램이 실행되는 기본 모드
-> 물리적인 영역으로 접근이 허용되지 않고 접근할 수 있는 메모리의 영역에 제한이 있음
- 커널 모드
-> 운영체제가 실행될 때의 모드
-> 메모리, 하드웨어 접근에 제한이 따르지 않음
- 쓰레드의 생성과 같이 운영체제에 의해 완성되는 연산을 위해서는 유저모드와 커널모드 간 전환이 이뤄져야 함
쓰레드 동기화 기법의 두 가지 방법
- 유저 모드 동기화
-> 커널 코드가 실행되지 않기 때문에 동기화를 위해 커널 모드로 전환히 불필요하여 성능상에 이점이 있음
-> 크리티컬 섹션(임계 영역) 기반 동기화
-> 인터락 함수 기반 동기화
- 커널 모드 동기화
-> 커널에서 제공하는 동기화 기능을 사용하기 때문에 성능의 저하가 있지만 유저 모드 동기화에서 제공하지 못하는 기능을 사용할 수 있음
-> 뮤텍스 기반 동기화 : 메모리 접근에 대한 동기화에 사용
-> 세마포어 기반 동기화 : 메모리 접근에 대한 동기화에 사용
-> 이름있는 뮤텍스 기반 동기화 : 메모리 접근에 대한 동기화에 사용
-> 이벤트 기반 동기화 : 실행 순서에 대한 동기화에 사용
크리티컬 섹션 기반의 동기화
- 크리티컬 섹션 기반의 동기화
-> 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 <process.h>
#define NUM_THREAD 50
unsigned threadInc(void * arg);
unsigned threadDes(void * arg);
long long num=0;
CRITICAL_SECTION cs;
int main(int argc, char *argv[])
{
HANDLE tHandles[NUM_THREAD];
int i;
InitializeCriticalSection(&cs);
for(i=0; i<NUM_THREAD; i++)
{
if(i%2)
tHandles[i]=(HANDLE)_beginthreadex(NULL, 0, threadInc, NULL, 0, NULL);
else
tHandles[i]=(HANDLE)_beginthreadex(NULL, 0, threadDes, NULL, 0, NULL);
}
WaitForMultipleObjects(NUM_THREAD, tHandles, TRUE, INFINITE);
DeleteCriticalSection(&cs);
printf("result: %lld \n", num);
return 0;
}
unsigned WINAPI threadInc(void * arg)
{
int i;
EnterCriticalSection(&cs);
for(i=0; i<50000000; i++)
num+=1;
LeaveCriticalSection(&cs);
return 0;
}
unsigned WINAPI threadDes(void * arg)
{
int i;
EnterCriticalSection(&cs);
for(i=0; i<50000000; i++)
num-=1;
LeaveCriticalSection(&cs);
return 0;
}
- 인터락 함수 기반의 동기화
-> 간편하게 임계 영역을 설정하기 위한 동기화 기법
-> 원자적 접근 보장 : 한 순간에 하나의 쓰레드에 의해서만 호출이 완료되도록 허용
LONG InterlockedIncrement(
LONG volatile *Addend
);
LONG InterlockedDecrement(
LONG volatile *Addend
);
-> InterlockedIncrement() / InterlockedDecrement()
* 전달된 변수의 값을 하나 증가 / 감소 시킴
'Programming > Network' 카테고리의 다른 글
열혈 TCP/IP 21-1. 비동기 Notification IO 모델의 이해 (0) | 2021.04.13 |
---|---|
열혈 TCP/IP 20-2. 커널모드 동기화 기법 (0) | 2021.04.11 |
열혈 TCP/IP 19-3. 커널 오브젝트의 두 가지 상태 (0) | 2021.04.11 |
열혈 TCP/IP 19-2. 윈도우 기반의 쓰레드 생성 (0) | 2021.04.11 |
열혈 TCP/IP 19-1. 커널오브젝트(Kernel Objects) (0) | 2021.04.11 |