크리티컬 섹션(Critical Section) & 뮤텍스(Mutex) & 이벤트(Event) & 세마포어(Semaphore)
Programming/Network 2011. 4. 27. 20:441. 크리티컬 섹션(Critical Section)이란?
- 유저레벨 어플리케이션 작성 시 가장 간단하게 상요할 수 있는 방법이다.
- 유저레벨의 동기화 방법 중 유일하게 커널 객체를사용하지 않으며 그 내부 구조가 단순하기 때문에
동기화 처리를 하는 데 있어서 속도가 빠르다는 장점이 있으며 동일한 프로세스내에서만 사용할 수 있다는 제약이
있다.
- 크리티컬 섹션은 커널 객체를 사용하지 않기 때문에 핸들을 사용하지 않고 대신 CRITICAL_SECTION라는 타입을
정의하여 사용하게 되며, 아래 4가지 Win32 API를 사용하여 동기화를 수행하게 된다.
◦VOID InitializeCriticalSection(LRCRITICAL_SECTION IpCriticalSection);
◦VOID DeleteCriticalSection(LRCRITICAL_SECTION IpCriticalSection);
◦VOID EnterCriticalSection(LRCRITICAL_SECTION IpCriticalSection);
◦VOID LeaveCriticalSection(LRCRITICAL_SECTION IpCriticalSection);
※ 커널 객체를 사용하지 않는 동기화 객체는 크리티컬 섹션뿐이며 뮤택스를 포함한 동기화 객체들,
스레드(Thread), 파일(File)들까지도 동기화를 위한 커널 객체를 포함하고 있다.
http://winnerz.tistory.com/
2. 뮤텍스(Mutex)란?
- 뮤텍스는 최초에 Signaled 상태로 생성되어지며, WaitForSingleObject()와 같은 대기 함수를 호출함으로써
NonSignaled 상태가 된다. WaitForSingleObject()와 같은 대기 함수에 대한 최초의 스레드 접근은 그 상태가
Signaled이므로 스레드가 대기없이 해당 코드 영역으로 진입하게 되며, 이 진입이 일어난 후에는 뮤텍스의 상태가
NonSignaled로 되므로 이후에 접근하는 스레드들은 대기하게 된다. 그리고 이후에 뮤텍스를 원래의 Signaled
상태로 바꾸어 주는 ReleaseMutex() 함수를 사용함으로써 대기하고 있던 스레드가 다시 실행하게 되는 것이다.
- 뮤텍스는 스레드가 여러 개 있더라도 자신이 소유한 스레드가 누구인지를 기억하고 있으며, Windows 운영체제는
뮤텍스가 반환되지 않은 상태에서 스레드가 종료될 경우 그 뮤텍스를 강제적으로 Signaled 해줌으로써 이를
대기하고 있던 스레드가 무한정 기다리는 일이 없도록 해준다.
- 뮤텍스는 뮤텍스를 소유한 스레드를 기억하고 있음으로써 같은 스레드가 같은 뮤텍스를 중복 호출하더라도 데드락
현상이 발생하기 않게 하고있다. 즉, 내부적으로 같은 스레드가 같은 뮤텍스를 소유하려 할 경우 뮤텍스의 내부적인
카운트만을 증가시켜 주고 이 스레드에 대한 진입은 허용하여 주게 된다. 그리고 이 내부적인 카운트가 0으로
내려갔을 경우에 Signaled 상태로 돌려줌으로써 다른 스레드에 대해서는 중복 호출한 스레드가 뮤텍스에 대한
사용을 모두 종료한 후에 진입하도록 하고 있으며, 이러한 기능은 같은 스레드의 재귀 호출에 의한 데드락 현상을
방지하여 주게 된다.
3. 이벤트(Event)란?
- 이벤트는 어떠한 사건에 대하여 알리기 위한 용도로 사용되는 동기화 객체이다. 이벤트 객체의 경우 우리가
Windows에서 메시지를 교환할 때 사용하는 개념과 같은 개념이다. 즉, Windows의 메시지 교환 방식은 이벤트에
기반한 방식이라고 이야기한다. 키보드가 눌려질 경우 WM_KEYDOWN, 마우스 왼쪽 버튼이 눌러질 경우
WM_LBUTTONDOWN과 같은 메시지가 날라오며, 이러한 신호는 이벤트를 통하여 통보하게 되는 것이다.
- 이벤트의 경우 SetEvent() 또는 ResetEvent()를 사용하여 동기화 객체들의 상태를 마음대로 바꿀 수 있게 된다.
4. 세마포어(Semaphore)란?
- 세마포어는 사용자가 지정한 개수만큼 이 동기화 객체로 보호하는 자원에 대하여 접근할 수 있도록 하고 있다.
즉, 세마포어에서는 사용 가능한 자원의 개수를 세팅할 수 있도록 하고 있으며, 그 값은 세마포어 초기화 시에
세팅하게 된다.
- 세마포어가 초기화되었을 때에는 뮤텍스와 마찬가지로 Signaled 상태로 되어 있으며, 세마포어의 자원이 하나
사용될 때마다 사용 가능한 자원의 개수는 1씩 감소하게 된다. 그리고 이 개수 값이 1 이상일 때까지는 Signaled
상태로 계속 유지되고 이 값이 0이 되면 세마포어의 상태는 NonSignaled가 되어 이 이후에 접근하는 스레드들에
대하여 대기하도록 만들게 된다. 그리고 사용 가능한 자원의 개수가 다시 1 이상이 되면 세마포어의 상태가 다시
Signaled 상태로 되어 대기하고 있던 스레드가 계속하여 세마포어의 자원을 사용할 수 있게 하는 것이다.
- 세마포어의 자원에 대한 반환은 ReleaseSemaphore() 함수를 사용하며, 자신이 사용한 자원의 개수에 대하여
lReleaseCount만큼 그 내부 카운터를 증가시키게 된다.
출처 : Windows 구조와 원리 그리고 Codes
'Programming > Network' 카테고리의 다른 글
socket error 메세지 (WSAGetLastError) (0) | 2011.09.07 |
---|---|
WaitForSingleObject 사용시 Thread 종료되었는지 주의할 것 (0) | 2011.09.07 |
동기화를 위한 커널 객체 (0) | 2011.04.27 |