- CSyncObject
: 스레드 동기화 클래스를 위한 공통의 인터페이스를 제공하는 역할을 한다.
순수 가상 함수(Pure Virtual Fuction)를 포함하고 있으므로 이 클래스를 직접 사용하지는 않는다.
- CCriticalSection, CEvent, CMutex, CSemaphore
: 운영체제에서 제공하는 스레드 동기화 객체(임계 영역, 이벤트, 뮤텍스, 세마포)를 편리하고 일관성 있게 사용할 수 있도록 만든 클래스다.
일반적으로 스레드 동기화 클래스라고 부를 때는 이 클래스를 의미한다.
- CSingleLock, CMultiLock
: 스레드 동기화 클래스를 편리하게 사용할 수 있ㄷ록 보조하는 역할을 한다.이 클래스는 CObject의 파생 클래스가 아닌 독립적인 클래스다.
스레드를 사용하는 경우
1. 두 개 이상의 스레드가 공유 리소스를 사용하는 경우
2. 하나의 스레드가 작업을 완료한 후, 기다리고 있던 다른 모든 스레드에게 알려주는 경우
윈도우에서 이러한 매개체 역할을 하는 것으로는 임계 영역, 이벤트, 뮤텍스, 세마포가 있으며 이들을 동기화 객체(Stnchronization Object)라 부른다.
임계 영역(Critical Section)
임계 영역은 같은 프로세스에 속한 스레드 간의 동기화를 위해 사용한다.
다른 스레드 동기화객체(이벤트, 뮤텍스, 세마포)와는 달리, 커널 모드가 아닌 사용자 모드에서 동작하므로 속도가 빠른 장점이 있다.
그러나 사용자 모드에서 동작하므로 서로 다른 프로세스에 속한 스레드 간의 동기화를 위한 목적으로는 사용할 수 없다는 특징이 있다.
두 스레드 중 먼저 Lock()을 호출하는 쪽이 공유 리소스를 접근할 수 있으며, 나중에 Lock()을 호출하는 쪽은 상대편이 Unlock()을 호출 할 때까지 대기하게 된다.
뮤텍스(Mutex, Mutual Exclusion)
뮤텍스는 임계 영역과 동일한 기능을 한다.
즉, 공유 리소스를 접근하는 다수의 스레드가 있을 때 오직 하나의 스레드만 접근할 수 있도록 하는 것이다. 뮤텍스는 임계 영역과 달리 커널 모드로 동작하기 때문에
속도는 느리지만 여러 프로세스에 속한 스레드 간의 동기화에 사용할 수 있다.
뮤텍스도 임게영역과 동일하게 Lock()을 먼저 호출한 쪽이 공유 리소스를 접근한 후 작업이 끝나면 Unlock()을 호출하여 기다리고 있던 다른 스레드에게 기회를
주는 방식이다. 단, Lock() 호출에 성공한 스레드가 해당 뮤텍스 객체를 소유한다는 것이다.
뮤텍스를 소유한 스레드만이 Unlock()을 호출하여 자신의 소유권을 포기할 수 있다.
이벤트(Event)
이벤트는 신호(Signaled)와 비신호(Nonsignaled) 두 개의 상태를 가진 동기화 객체다.
1. 이벤트 객체를 비신호 상태로 생성한다.
2. 하나의 스레드가 초기화 작업을 진행하고, 나머지 스레드는 이벤트 객체에 대해 Lock()을 호출함으로써 이벤트 객체가 신호 상태가 되기를 기다린다.(Sleep 상태)
3. 스레드가 초기화 작업을 완료하면, 이벤트 객체를 신호 상태로 바꾼다.
4. 기다리고 있던 모든 스레드가 깨어나서 작업을 진행한다.
이벤트 특성에는 자동 리셋, 수동 리셋
- 자동 리셋(Auto Reset)
: 이벤트 객체를 신호 상태로 바꾸면, 기다리는 스레드 중 하나만 깨운 후 자동으로 비신호 상태가 된다. 신호 상태에서 비신호 상태로 되는 것을 리셋이라 부른다.
- 수동 리셋(Manual Reset)
: 이벤트 객체를 신호 상태로 바꾸면, 계속 신호 상태를 유지한다. 결과적으로는 기다리는 스레드를 모두 깨우게 된다. 리셋을 하려면 명시적으로 함수를 호출해야 한다.
* 임계 영역 또는 뮤텍스와의 차이점
- 두 개 이상의 스레드가 공유 리소스를 사용하는 경우 -> 임계 영역 또는 뮤텍스를 사용한다.
- 하나의 스레드가 작업을 완료한 후, 기다리고 있던 다른 모든 스레드에게 알려주는 경우 -> 이벤트를 사용한다.
세마포(Semaphore)
세마포는 한정된 개수의 자원을 여러 스레드가 접근하려고 할 때, 이를 제어하는 동기화 객체다.
다른 동기화 객체와 달리 세마포는 사용 가능한 리소스의 개수에 해당하는 리소스 카운트(Resource Count) 값을 유지하므로, 수행될 수 있는 스레드 개수를 조절할 수 있다.
1. 세마포를 생성한다. 이 때 사용 자능한 자원의 개수로 리소스 카운트를 초기화한다.
2. 리소스를 사용할 스레드는 자신이 필요한 리소스 개수만큼 Lock()을 호출하며, Lock()이 성공할 때마다 리소스 카운트 값이 1씩 감소한다.
만약 리소스 카운트가 0인 상태에서 Lock()을 호출하면 해당 스레든 대기한다.
3. 리소스 사용을 마친 스레드는 자신이 사용한 리소스 개수만큼 Unlock()을 호출하며, 이 때마다 리소스 카운트 값이 1씩 증가한다.
CSingleLock, CMultiLock
스레드 동기화 클래스를 편리하게 사용할 수 있도록 보조하는 역할을 한다.
- CSingleLock
Lock()을 호출하여 뮤텍스 객체를 소유한 스레드가 실행 중 예외 상황이 발생하여 종료하게 되면, Unlock()이 호출되지 못하므로 문제가 된다.
그러한 문제를 해결할 수 있는 것으로, CSingleLock을 이용하는 방법이 있다.
예외 상황이 발생할 경우를 대비하여 소멸자에서는 Unlock()을 호출한다.
- CMultiLock
하나의 스레드가 여러 개의 동기화 객체를 사용하는 경우, 각 동기화 객체에 대해 동시에 Lock()을 호출해야 하는 경우가 발생한다.
이 경우 CMultiLock 객체를 사용하면 하나 또는 모든 동기화 객체가 사용 가능한지 여부를 판단할 수 있다.
'OS' 카테고리의 다른 글
윈도우 메시지 처리 과정 (0) | 2014.11.14 |
---|---|
문맥교환 (0) | 2014.11.13 |
RAID (0) | 2014.10.17 |
모놀리식 커널 (0) | 2014.10.17 |
가상메모리 사용 이유 (0) | 2014.10.17 |