티스토리 뷰
MFC 스레드 동기화 - 예외처리
CSingleLock, CMultiLock 클래스는 스레드 동기화 클래스를 편리하게 사용할 수 있도록 보조하는 역활
1. CSingleLock
Lock()을 호출하여 뮤텍스 객체를 소유한 스레드가 실행 중 예외 상황이 발생하여 종료하게 되면, Unlock() 이 호출되지 못하는 문제가 발생한다.
1
2
3
4
5
6
7 |
CMutex g_mutex(...);
MyThread()
{
g_mutex.Lock();
// 예외 상황 발생
g_mutex.Unlock();
} |
cs |
이런 경우, 아래 코드와 같이 변수 lock 이 스택에 생성되므로 예외 상황이 발생하여 스레드가 종료하게 되면 자동으로 lock의 소멸자가 호출되고, 소멸자에서는 unlock()을 호출한다. 즉, Lock() 이 호출되면 unlock()이 반드시 호출된다는 것이 보장되는 것이다. 이 같은 기법은 뮤텍스 이외에 임계 영역, 세마포, 이벤트에도 모두 적용할 수 있다.
1
2
3
4
5
6
7
8 |
CMutex g_mutex(...);
MyThread()
{
CSingleLock lock(&g_mutex);
g_mutex.Lock();
// 예외 상황 발생
g_mutex.Unlock();
} |
cs |
2. CMultiLock
하나의 스레드가 여러 개의 동기화 객체를 사용하는 경우, 각 동기화 객체에 대해 동시에 Lock() 을 호출해야 하는 경우가 발생한다. 이 경우 CMultiLock 객체를 사용하면 하나 또는 모든 동기화 객체가 사용 가능한지 여부를 판단할 수 있다.
예로, 다음 코드는 3개의 이벤트 객체가 모두 신호 상태가 되기를 대기하는 것을 보여준다.
1
2
3
4
5
6
7
8 |
CEvent g_event[3];
CSyncObject* g_pSyncObjects[3] = { &g_event[0], &g_event[1], &g_event[2] };
MyThread()
{
CMultiLock multilock(g_pSyncObjects, 3);
multilock.Lock();
...
} |
cs |
3개의 이벤트 객체 중 하나가 신호 상태가 되기를 대기하려면 CMultiLock::Lock() 호출 방법을 다음과 같이 변경한다.
1
2
3
4
5
6
7
8 |
CEvent g_event[3];
CSyncObject* g_pSyncObjects[3] = { &g_event[0], &g_event[1], &g_event[2] };
MyThread()
{
CMultiLock multilock(g_pSyncObjects, 3);
multilock.Lock(INFINITE, FALSE);
...
} |
cs |
CMultiLock 은 뮤텍스, 이벤트, 세마포 객체를 혼합하여 사용할 수 있으나,
임계 영역 객체에 대해서는 사용할 수 없다는 점에 주의해야 한다.