728x90

유저 모드와 커널 모드

- 유저 모드

    -> 응용 프로그램이 실행되는 기본 모드

    -> 물리적인 영역으로 접근이 허용되지 않고 접근할 수 있는 메모리의 영역에 제한이 있음

- 커널 모드

    -> 운영체제가 실행될 때의 모드

    -> 메모리, 하드웨어 접근에 제한이 따르지 않음

- 쓰레드의 생성과 같이 운영체제에 의해 완성되는 연산을 위해서는 유저모드와 커널모드 간 전환이 이뤄져야 함

 

쓰레드 동기화 기법의 두 가지 방법

- 유저 모드 동기화

    -> 커널 코드가 실행되지 않기 때문에 동기화를 위해 커널 모드로 전환히 불필요하여 성능상에 이점이 있음

    -> 크리티컬 섹션(임계 영역) 기반 동기화

    -> 인터락 함수 기반 동기화

- 커널 모드 동기화

    -> 커널에서 제공하는 동기화 기능을 사용하기 때문에 성능의 저하가 있지만 유저 모드 동기화에서 제공하지 못하는 기능을 사용할 수 있음

    -> 뮤텍스 기반 동기화 : 메모리 접근에 대한 동기화에 사용

    -> 세마포어 기반 동기화 : 메모리 접근에 대한 동기화에 사용

    -> 이름있는 뮤텍스 기반 동기화 : 메모리 접근에 대한 동기화에 사용

    -> 이벤트 기반 동기화 : 실행 순서에 대한 동기화에 사용

 

크리티컬 섹션 기반의 동기화

- 크리티컬 섹션 기반의 동기화

    -> 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()

        * 전달된 변수의 값을 하나 증가 / 감소 시킴

728x90

+ Recent posts