검색결과 리스트
동기화객체에 해당되는 글 2건
- 2011.08.26 동기화객체 비교
글
동기화 객체-ml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />-ml:namespace prefix = o />
두 개 이상의 thread가 공유자원에 대해 동시에 접근할 때, 데이터의 일관성을 보장할 수 없기 때문에 이를 막기 위해 공유자원을 적절히 사용할 수 있게 하는 방법을 동기화라 한다.
동기화 객체에는 아래와 같이 user-mode 객체와 kernel-mode 객체로 나뉜다.
object | Linux/Unix | Windows |
File Lock | kernel-mode | kernel-mode |
† Critical Section | 없음 | user-mode 한 프로세스 내에서만 사용가능 |
Interlock | 없음 | user-mode 한 프로세스 내에서만 사용가능 |
† Mutex | POSIX 함수 한 프로세스 내에서만 사용가능 하나의 공유자원 동기화에 사용 | kernel-mode 프로세스끼리도 사용가능 타임아웃기능 사용가능 하나의 공유자원 동기화에 사용 |
† Semaphore | kernel-mode POSIX 함수 프로세스끼리도 사용가능 다중 공유자원 동기화에 사용 | kernel-mode 프로세스끼리도 사용가능 타임아웃기능 사용가능 다중 공유자원 동기화에 사용 |
Condition Variable | POSIX 함수 타임아웃기능 사용가능 다중 스레드를 동시에 깨울 수 있음 | 없음 |
† Event | 없음 | kernel-mode 프로세스끼리도 사용가능 타임아웃기능 사용가능 다중 스레드나 프로세스를 동시에 깨울 수 있음 |
여기서는 †표시된 가장 많이 사용되는 객체들만 정리하기로 함.
0. 사전지식
※ User-mode 객체
커널 영역의 객체를 접근할 필요 없이 메모리 상에서 객체를 생성하여 운용하므로 연산이 빠르다는 장점이 있지만 프로세스 간의 동기화는 할 수 없다.
※ Kernel-mode 객체
커널 객체를 사용한 동기화는 signaled, nonsignaled 둘 중 하나의 상태로 존재한다.
mutex, semaphore, event의 경우 생성할 때에는 signaled-mode이지만, 대기함수인
WaitForSingleObject()나 WaitForMultipleObject()를 사용하여 nonsignaled-mode로 만들 수 있다.
- signaled
thread가 해당 객체에 접근이 가능하며, 접근한 thread는 객체를 사용 가능하다.
- nonsignaled
thread는 해당 객체에 접근할 수 없고 signaled될 때까지 대기한다. ※ 관련용어 - critical section 임계영역. 공유 자원을 접근하는 프로세스 내부의 코드 영역. 동기화 객체와 같은 단어지만 그 뜻은 다르다. - deadlock 교착상태. 두 개 이상의 프로세스들이 더 이상 진행을 할 수 없는 상태. - livelock 라이브락. 두 개 이상의 프로세스들이 다른 프로세스의 상태 변화에 따라 자신의 상태를 변화시 키는 작업만을 수행하고 있는 상태. - mutual exclusion 상호배제. 한 프로세스가 공유 자원을 접근하는 임계영역 코드를 수행하고 있으면 다른 프로세스 들은 공유 자원을 접근하는 임계영역 코드를 수행 할 수 없는 조건. - race condition 경쟁상태. 두 개 이상의 프로세스가 공유 자원을 동시 접근하려는 상태. - starvation 기아. 특정 프로세스가 수행 가능한 상태임에도 불구하고 매우 오랜 기간 동안 자원을 사용하지 못하는 상태. 1. MUTEX 뮤텍스 생성 HANDLE CreateMutex ( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName ); 뮤텍스 소유 HANDLE OpenMutex ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName ); 뮤텍스 소유 해제 BOOL ReleaseMutex ( HANDLE hMutex ); 뮤텍스 삭제 HRESULT CloseHandle ( HANDLE hHandle ); 2. SEMAPHORE - 내부 count만큼 thread가 접근가능하며 count가 0이 되었을 때는 다른 thead의 접근을 차단. 세마포어 생성 HANDLE CreateSemaphore ( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName ); 세마포어 진입 HANDLE OpenSemaphore ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName ); 세마포어 진입해제 BOOL ReleaseSemaphore ( HANDLE hSemaphore, LONG lReleaseCount, 세마포어 삭제 HRESULT CloseHandle ( HANDLE hHandle ); 3. CRITICAL SECTION - 같은 프로세스 내에서만 사용될 수 있는 user-mode 동기화 객체. - 공유자원을 다 사용한 후 LeaveCriticalSection을 호출하여 다른 thread의 접근을 허용. 크리티컬 섹션의 초기화 void InitializeCriticalSection ( LPCRITICAL_SECTION lpCriticalSection ); 크리티컬 섹션에 진입 void EnterCriticalSection ( LPCRITICAL_SECTION lpCriticalSection ); 크리티컬 섹션에 진입해제 void LeaveCriticalSection ( LPCRITICAL_SECTION lpCriticalSection ); 크리티컬 섹션을 삭제 void DeleteCriticalSection ( LPCRITICAL_SECTION lpCriticalSection ); Spin Lock Count를 설정. BOOL InitializeCriticalSectionAndSpinCount ( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount ); * kernel-mode에 비해 빠르지만 한 프로세스 안에서만 사용이 가능하다. (mutex보다 2~10배) 대기 thread가 많을 경우, kernel-mode로 대기 thread를 관리하므로 user-mode일 때만 빠름. * 유저영역 메모리에 존재하는 구조체이므로 한 process에 속한 thread들의 동기화만 가능하다. * 하나의 thread에서 여러 번 호출할 때에는 이를 무시한다. (deadlock 방지를 위해) * mutex와 달리 소유한 thread가 비정상 종료하면 다른 thread들은 무한정 대기한다. ※critical section의 동작 ※ Spin Lock 위에서처럼 critical section은 multiple-CPU상에서 critical section을 사용할 수 없는 경우, kernel-mode의 semaphore를 사용하여 대기중인 thread를 관리하게 된다. semaphore는 critical section을 다른 thread에서 사용 중이라면 context-switching을 하여 CPU의 소유권을 반납하게 되고 다시 자신의 차례가 되면 다시 critical section의 사용여부를 조사하고, critical section을 아직 사용 중이라면 다시 위의 동작을 반복하며 대기(busy waiting) 하게 된다. 이러한 빈번한 context-switch를 방지하기 위해 일정시간 동안 critical section의 사용이 끝나기를 기다리게 하는 것이 spin lock이다. ※ Context Switch CPU가 다른 프로세스로 교환하기 위해 이전의 프로세스의 상태를 보관하고, 새로운 프로세스의 보관된 상태를 적재하는 작업으로 보통 process context switch가 thread context switch보다 시간이 더 소요된다. 4. EVENT - 특정 상황이 발생했을 때 이를 알리기 위해 사용하는 kernel-mode 동기화 객체. - mutex, semaphore, critical section은 공유자원에 대한 보호에 사용되지만, event는 주로 thread의 작업 우선순위나 작업시기의 조정을 위해 쓰임 이벤트 생성 HANDLE OpenEvent ( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName ); 이벤트 지정 BOOL SetEvent ( HANDLE hEvent ); 이벤트 해제 BOOL ResetEvent ( HANDLE hEvent ); 이벤트 삭제 HRESULT CloseHandle ( HANDLE hHandle );
- 모든 thread에 사용되는 kernel-mode 동기화 객체.
- 공유자원에 대해 한 thread가 단독으로 점유하며 다른 thread의 접근을 차단.
- 공유자원을 다 사용한 후 ReleaseMutex를 호출하여 다른 thread의 접근을 허용.
* critical section은 구조체의 값을 통해 잠금을 하지만 mutex는 객체를 생성하기 때문에 critical section보다 느리다.
* mutex name을 가지며 name은 유일한 값이 된다.
* mutex를 소유한 thread가 mutex의 소유를 반납하지 않고 비정상 종료될 경우 강제로 해제시켜 다른 thread에서 소유할 수 있도록 한다.
* mutex를 소유한 thread가 중복으로 호출할 경우 critical section처럼 진입을 허용하고 내부 count만 증가시켜 deadlock을 발생시키지 않는다.
* mutex는 다른 말로 상호배제 semaphore라고도 불리는데 이는 mutex가 특별한 형태의 binary semaphore이다. (일반 binary semaphore와 다른 이유는 소유권이 있다는 점이다)
- mutex와 비슷하지만 접근 가능한 thread의 개수를 지정 가능한 kernel-mode 동기화 객체.
- ReleaseSemaphore를 호출하여 count를 1 증가시켜 다른 thread의 접근을 허용
LPLONG lpPreviousCount );
* mutex와 마찬가지로 named semaphore는 프로세스 간 동기화도 가능
* thread나 process에 무관하게 진입 시 count를 증가
* 하나의 thread에서 모두 소유한 상태에서 다시 진입하면 deadlock이 발생
* binary semaphore
0이나 1의 값을 가지는 semaphore로 0이면 사용불가, 1이면 사용 가능하다.
* counting semaphore
내부 카운터를 사용하여 여러 차례 획득하고 반환할 수 있는 semaphore로 생성 시 초기 Token값을 지정할 수 있다.
- 공유자원에 대해 한 thread가 단독으로 점유하며 다른 thread의 접근을 차단.
1) thread가 EnterCriticalSection()으로 진입하는 경우, CRITICAL_SECTION 구조체 내부의 변수를 검사하여 off이면 on으로 변경한 후 작업을 진행. (user-mode에서 이루어짐)
2) 한 thread가 진입한 경우, single-CPU상에서는 kernel-mode로 넘어가 동기화 작업이 수행되고, multiple-CPU상에서는 Spin Count만큼 busy-waiting하며 lock해제를 대기.
3) kernel-mode로 넘어가면 해당 thread는 semaphore를 이용한 wait상태가 됨.
4) thread가 LeaveCriticalSection()으로 진입 해제하면 CRITICAL_SECTION 구조체 내부의 변수를 off로 변경하고, semaphore를 이용한 경우에는 기다리고 있는 thread에게 통지를 함.
5) EnterCriticalSection()으로 진입한 thread에서 EnterCriticalSection()을 다시 한번 호출하면, 내부적으로 count 변수 값을 올려서 deadlock을 막음. (EnterCriticalSection()을 호출한 횟수만큼 LeaveCriticalSection()을 해야 함)
* 윈도우 시스템에서만 존재하는 동기화 객체이다.
* 다른 객체들은 thread가 진입하게 되면 nonsignaled 상태로 자동으로 변경되게 된다.
이를 자동리셋모드 (auto-reset mode)라고 하는데 event는 자동리셋모드는 물론 수동리셋모드(manual-reset mode)도 사용할 수 있다.
'-- VC++' 카테고리의 다른 글
익스플로어의 입력박스 후킹 (0) | 2012.10.09 |
---|---|
Thread 동기화 객체 및 IPC의 선택 (0) | 2011.08.26 |
OutputDebugString (0) | 2010.08.06 |
VC++ 코드 실행 시간 측정 방법 정리 (0) | 2009.11.19 |
APC(Asynchronous procedure call)에 대하여 (0) | 2009.10.29 |
RECENT COMMENT