XIV : 쓰레드 동기화 기법 II
뇌를 자극하는 윈도우즈 시스템 프로그래밍 을 읽고 정리한 문서입니다 ;)
실행순서에 있어서의 동기화
쓰레드의 실행순서를 동기화시킨다는 것은, 정확히는 메모리에 접근하는 쓰레드의 실행순서를 동기화 하는 것이다.
생산자/소비자 모델은 실행되는 쓰레드의 순서가 중요한 상황을 설명할 때 종종 소개되는 모델이다.
이벤트 기반 동기화
Windows 개발자들은 쓰레드의 실행순서를 동기화한다고 하면, 가장 먼저 떠올리는 것이 이벤트 기반 동기화 기법이다.
세마포어나 뮤텍스와 마찬가지로 이 기법에서도 동기화를 위한 오브젝트가 사용되는데, 이를 이벤트 오브젝트라고 한다.
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName
);
BOOL bManualReset
: 이벤트를 수동 리셋 모드로 생성할 것인지, 자동 리셋 모드로 생성할 것인지에 대한 인자이다. 이는 대기중이던 쓰레드가WaitForSingleObject
등으로 이벤트 알림을 받았을 때 해당 이벤트가 Signaled를 유지할지, Non-Signaled로 돌아갈지를 결정한다.BOOL bInitialState
: 이벤트의 초기 오브젝트 상태를 결정짓는다.true
인 경우 이벤트가 Signaled상태로 생성된다.
쓰레드나 프로세스의 커널 오브젝트의 경우, 종료될 경우 해당 커널 오브젝트는 Signaled 상태로 자동 변경된다. 하지만 이벤트의 경우 이처럼 자동 변경되는 조건이라는 것이 따로 존재하지 않고, 프로그래머의 요청에 의해 Signaled 상태가 되게 된다.
이벤트의 상태를 변경시키기 위해서는 ResetEvent()
함수와 SetEvent()
함수를 사용한다.
수동 리셋 모드 이벤트는 둘 이상의 쓰레드를 동시에 깨워서 실행해야 할 때 아주 좋은 도구가 된다.
이벤트 더하기 뮤텍스
이벤트와 뮤텍스를 동시에 사용해서 동기화해야 하는 상황은 실무 개발환경에서 자주 접하는 상황이다. 이벤트 오브젝트로는 생산자/소비자 모델을 구현하고, 이 과정에서 소비자 쓰레드가 둘 이상인 관계로 이들 간 동기화를 위해 뮤텍스를 사용하는 것이다.
타이머 기반 동기화
타이머 오브젝트는 정해진 시간이 지나면 자동으로 Signaled 상태가 되는 특성을 지닌다. 때문에 이름도 Waitable Timer 이다.
- 수동 리셋 타이머
- 가장 일반적인 타이머로서, 알람과 동일한 방식으로 동작하게 된다.
- 주기적 타이머
- 수동 리셋 타이머에 주기적인 반복성을 더한 형태이다.
수동 리셋 타이머
HANDLE CreateWaitableTimer(
LPSECURITY_ATTRIBUTES lpTA,
BOOL bManualReset,
LPCTSTR lpTimerName
);
BOOL bManualReset
: 타이머 오브젝트를 수동 리셋 모드로 생성할 것인지, 자동 리셋 모드로 설정할 것인지에 대한 플래그이다.
하지만 이는 기존 이벤트에 비해 bInitialState
가 없다. 이는 타이머의 성격 상, 바로 울리기 위해 만든 것이 아니므로 Non-Signaled 상태로 생성되기 때문이다.
이후 생성한 타이머 오브젝트에 알람 시간을 설정해야 한다.
BOOL SetWaitableTimer(
HANDLE hTimer,
const LARGE_INTEGER* pDueTime,
LONG lPeriod,
PTIMERAPCROUTINE pfnCompletionRoutine,
LPVOID lpArgToCompletionRoutine,
BOOL fResume
);
const LARGE_INTEGER* pDueTime
: 알람이 울리는 시간을 의미하는 매개변수이다. 만일 양수 값이 전달되면 절대시간을 의미하고, 음수 값이 전달되면 상대시간을 의미하게 된다.LONG lPeriod
: 타이머가 주기적으로 알람을 울리게 할 때 사용하는 전달인자이다.0
을 전달하면 주기적인 알람을 사용하지 않게 된다.
주기적 타이머
만일 중간에 타이머를 해제하고자 하는 경우에는 CancelWaitableTimer()
함수를 이용한다.
단 이는 타이머를 중지시킬 뿐 타이머를 소멸시키거나 자원을 반환하지 않는다. 타이머의 소멸과 자원 반환은 여느 커널 오브젝트와 마찬가지로 CloseHandle
함수를 호출하면 된다.
이것만은 알고 갑시다
- 실행순서 동기화와 이벤트 오브젝트
- 쓰레드의 실행순서가 중요한 이슈인 경우에는 실행순서 동기화를 고려해야 한다. 이를 위해서 Windows에서는 이벤트 오브젝트 기반의 동기화 기법을 제공한다.
- 타이머 기반 동기화
- 타이머 역시 동기화 오브젝트이고, 이는 다른 오브젝트와 달리 일정 시간이 지나면 자동으로 Signaled 되는 특징을 가지고 있다.
- 이벤트 더하기 뮤텍스
- 이벤트를 이용하여 생산자/소비자 등의 모델을 설계하고, 여러 쓰레드 간 공유 자원을 관리하기 위해 뮤텍스 등의 동기화 오브젝트를 쓰는 등 실제 개발 시에는 다양한 조합으로 구성되는 경우가 많다.
'공부한 이야기 > 윈도우 OS' 카테고리의 다른 글
XV : 쓰레드 풀링 (0) | 2023.04.29 |
---|---|
XIII : 쓰레드 동기화 기법 I (0) | 2023.04.29 |
XII : 쓰레드의 생성과 소멸 (0) | 2023.04.29 |
XI : 쓰레드의 이해 (0) | 2023.04.29 |
X : 컴퓨터 구조에 대한 세 번째 이야기 (0) | 2023.04.29 |