728x90

뮤텍스의 생성 및 실행

- CreateMutex : 성공 시 Mutex 핸들, 실패 시 NULL 반환

    -> 커널 오브젝트 생성을 동반하기 때문에 핸들도 반환되고 핸들 테이블의 상속을 결정하는 보안 설정을 함

    -> 소유자를 지정하면 열쇠를 만든사람이 소유하는지 열쇠를 만든 사람도 소유의 권한을 가지지 않고 누구나 소유할 수 있는 지를 결정

HANDLE CreateMutexA(
  LPSECURITY_ATTRIBUTES lpMutexAttributes,	// 보안 설정
  BOOL                  bInitialOwner,		// 열쇠의 소유
  LPCSTR                lpName				// 뮤텍스 이름
);
DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD  dwMilliseconds
);	// 지정한 오브젝트가 Signaled 상태가 되기를 기다리는 함수

BOOL ReleaseMutex(
  HANDLE hMutex
);

- WaitForSingleObject(), ReleasMutex()를 통해서 뮤텍스(열쇠)를 획득하고 반납

- 뮤텍스를 커널 오브젝트라고 생각하면 WaitForSingleObject()가 빠져나오기 위해선 뮤텍스가 Signaled 상태가 되야 함

    -> ReleaseMutex()는 뮤텍스를 Signaled 상태가 되게 하는 함수

    -> WaitForSingleObject()는 뮤텍스를 Non-Signaled 상태로 바꾸게 되는 함수

- 쓰레드가 임계 영역으로 들어가기 전 뮤텍스를 얻기 위해 뮤텍스 핸들을 인자로 전달하면서 WaitForSingleObject() 함수를 호출하고 뮤텍스가 획득 가능 상태라면 Signaled 상태에 있고 뮤텍스를 획득하면서 임계 영역에 진입

- WaitForSingleObject 함수는 매개변수로 호출한 오브젝트가 Signaled 상태가 되기를 기다리기 때문에 다른 쓰레드는 임계 영역으로의 진입이 불가능

- 임계 영역에 진입한 쓰레드가 빠져나오면서 ReleaseMutex 함수를 호출하면 뮤텍스는 Signaled 상태가 되어 다른 쓰레드가 획득할 수 있게 되어 다른 쓰레드의 진입을 허용함

int main(int argc, char *argv[]) 
{
	HANDLE tHandles[NUM_THREAD];
	int i;

	hMutex=CreateMutex(NULL, FALSE, NULL);
	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);
	CloseHandle(hMutex);
	printf("result: %lld \n", num);
	return 0;
}

unsigned WINAPI threadInc(void * arg) 
{
	int i;

	WaitForSingleObject(hMutex, INFINITE);
	for(i=0; i<50000000; i++)
		num+=1;
	ReleaseMutex(hMutex);

	return 0;
}
unsigned WINAPI threadDes(void * arg)
{
	int i;

	WaitForSingleObject(hMutex, INFINITE);
	for(i=0; i<50000000; i++)
		num-=1;
	ReleaseMutex(hMutex);

	return 0;
}

세마포어의 생성 및 실행

HANDLE CreateSemaphoreA(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  LONG                  lInitialCount,		
  // 세마포어가 가지는 열쇠의 개수(값) = 임계 영역에 동시 접근할 수 있는 쓰레드 수
  LONG                  lMaximumCount,	// 세마포어가 가질 수 있는 최대 열쇠의 수 (InitialCount 이상)
  LPCSTR                lpName
);
BOOL ReleaseSemaphore(
  HANDLE hSemaphore,
  LONG   lReleaseCount,
  LPLONG lpPreviousCount
);

- WaitForSingleObject, ReleaseSemaphore 함수가 호출되면 세마포어 카운트가 감소 / 증가됨

- 세마포어 카운트 값이 0이 되면 Non-signaled 상태가 됨

- Signaled 상태로 계속 있기 때문에 WaitForSingleObject를 호출해도 임계 영역에 다른 쓰레드도 진입 가능

static HANDLE semOne;
static HANDLE semTwo;
static int num;

int main(int argc, char *argv[])
{
	HANDLE hThread1, hThread2;
	semOne=CreateSemaphore(NULL, 0, 1, NULL);
	semTwo=CreateSemaphore(NULL, 1, 1, NULL);

	hThread1=(HANDLE)_beginthreadex(NULL, 0, Read, NULL, 0, NULL);
	hThread2=(HANDLE)_beginthreadex(NULL, 0, Accu, NULL, 0, NULL);

	WaitForSingleObject(hThread1, INFINITE);
	WaitForSingleObject(hThread2, INFINITE);
	
	CloseHandle(semOne);
	CloseHandle(semTwo);
	return 0;
}

unsigned Read(void * arg)
{
	int i;
	for(i=0; i<5; i++)
	{
		fputs("Input num: ", stdout);

		WaitForSingleObject(semTwo, INFINITE);
		scanf("%d", &num);
		ReleaseSemaphore(semOne, 1, NULL);
	}
	return 0;	
}
unsigned Accu(void * arg)
{
	int sum=0, i;
	for(i=0; i<5; i++)
	{
		WaitForSingleObject(semOne, INFINITE);
		sum+=num;
		ReleaseSemaphore(semTwo, 1, NULL);
	}
	printf("Result: %d \n", sum);
	return 0;
} // 세마포어로 실행 순서 조절

이벤트의 생성 및 실행

- createEvent : 성공 시 Event 핸들, 실패 시 NULL 반환

    -> bManualReset : True 전달 시 manual-reset 모드,  False 전달 시 auto-reset 모드

    -> bInitialState : True 전달 시 signaled 상태, False 전달 시 non-signaled 상태의 오브젝트 생성

HANDLE CreateEvent (LPSECURITY_ATTRIBUTES lpEventAttributes, WINBOOL bManualReset, 
				WINBOOL bInitialState, LPCWSTR lpName);

- 이벤트 상태의 변경 : manual-reset 모드로 생성했으면 상태를 수동으로 변경

BOOL SetEvent (HANDLE hEvent);		// non-signaled로 변경
BOOL ResetEvent (HANDLE hEvent);	// signaled로 변경

 

728x90

+ Recent posts