http://hyurichel.tistory.com/entry/InitializeCriticalSectionAndSpinCount
InitializeCriticalSectionAndSpinCount
TCP / IP NetWork 2008/01/10 09:52어제 정리했다시피 EnterCriticalSection 에서는 시스템 메모리가 부족할 때 오류가 발생합니다. 이것을 처리해 주기 위해서 throw-catch를 이용하거나 InitializeCriticalSectionAndSpinCount로 초기화 하는 방법을 제시 했었습니다.
그렇다면 InitializeCriticalSectionAndSpinCount이 뭐냐!!?
msdn을 뒤져보니까
BOOL InitializeCriticalSectionAndSpinCount(
LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
Return. 성공하면 0이 아닌 값.
실패하면 0이 나옴. GetLastError로 에러를 살펴보면 되겠습니다.
이렇게 생겼습니다. 리턴값도 있고 기존의 것과 다른 인자가 하나 더 들어가는군요. 바로 dwSpinCount. Spin을 할 횟수를 지정하면 됩니다.
dwSpinCount는 싱글코어일 경우에 인자가 무시됩니다.(자동으로 0으로 셋팅됩니다)
멀티코어일 경우, 만약 Critical Section이 이용되지 않으면, Critical Section과 함께 세마포어 연합(?) 의 기다리는 동작이 Thread Spin을 부를 때 dwSpinCount만큼 부르게 됩니다.
만약 Spin동작에서 CriticalSection이 무효화 된다면 부르게 되는 Thread는 기다리는 동작을 피하게 됩니다.
...이게 뭔소리냐-_- 직독직해를 해버리니까 이따위로 나오는군요. 대충 의미를 되세겨 봅시다.
Spin은 Wait 상태로 들어가기 전에 함수의 인자로 주어진 dwSpinCount만큼 루프를 돈다는 의미입니다. 루프 도는 중간에 Critical Section을 획득할 수 있다면 Thread를 교체하는 (Thread Context Switch)가 발생하지 않고 임계영역안에 접근 가능하다는 의미. 검색을 해보니까 dwSpinCount를 2000정도로 주는 것이 좋다고 합니다.
예를 들어보자면 1번 쿼리와 2번 쿼리가 있다고 했을 때 2번 쿼리에서 어는 특정 테이블을 변경하고 있다고 해 봅시다. 그런데 1번 쿼리에서 2번 쿼리가 변경하고 있는 테이블 값에 접근을 하려고 하는 경우 Critical Section에 의해서 접근이 불가됩니다. 이 때 일반적인 CriticalSection이라면 대기상태로 돌입하게 되는데, SpinCount가 지정되어 있다면 2번이 빠리 끝나기를 바라며 dwSpinCount만큼 재접근을 하는 겁니다. 그리고 실패해버리면 기다리는 모드로 들어가게 되고 성공하면 접근하는 것입니다.
이렇게 되면 싱글코어에서는 별 의미없겠지만 다중 프로세서일 경우에는 많은 의미가 생기겠지요? Thread의 ContextSwitch에 부하가 있는 데 그것을 피할 수 있을 가능성이 높아지겠지요. 기다리는 모드로 돌입하기 전에 접근 가능하는 경우가 꽤 많을 테니까요. 이상.
아래 링크는 위 글을 좀 더 간략하게 정리한 내용
http://blog.daum.net/jangun95/37
InitializeCriticalSectionAndSpinCount 함수
EnterCriticalSection 에서는 시스템 메모리가 부족할 때 오류가 발생합니다.
이것을 처리해 주기 위해서 try-catch를 이용해 예외처리를 하거나, InitializeCriticalSection 함수 대신 InitializeCriticalSectionAndSpinCount 함수를 이용합니다.
BOOL InitializeCriticalSectionAndSpinCount(
LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
InitializeCriticalSection 함수와 비교해보면 dwSpinCount라는 인자가 하나 더 추가되어 있습니다.
Spin은 Wait 상태로 들어가기 전에 함수의 인자로 주어진 dwSpinCount만큼 루프를 돈다는 의미입니다.
루프 도는 중간에 Critical Section을 획득할 수 있다면 Thread를 교체하는 Thread Context Switch가 발생하지 않고 임계영역안에 접근 가능하다는 말입니다.
dwSpinCount는 2000정도로 주는 것이 좋다고 합니다.
마지막으로 InitializeCriticalSectionAndSpinCount 함수를 사용하고 컴파일 시 오류가 발생한다면
StdAfx.h 에 _WIN32_WINNT 선언부를 다음과 같이 수정해 주십시오.
#define _WIN32_WINNT 0x0501 --> 윈도우 버전이 XP 이상일 경우를 말합니다.
[자료출처 : http://hyurichel.tistory.com]
http://bombfox.tistory.com/12
critical section을 위해 critical section object을 초기화 하고 겉돌기 횟수(spin count)를 설정한다. 스레드가 락이 걸린 critical section을 얻기 위해 시도했을 때, 스레드는 겉돈다(spin) : 그 것은 루프를 들어간다. 그 루프는 겉돌기 횟수만큼 반복하여 락이 해제됬는지를 보면서 검사한다. 만약 루프가 끝날 때까지 락이 해제가 되지 않았다면, 그 스레드는 락이 해제될 때 까지 sleep 상태에로 전이된다.
Critical Section Objects 사용 예
1: // Global variable
2: CRITICAL_SECTION CriticalSection;
3:
4: int main( void )
5: {
6: ...
7:
8: // Initialize the critical section one time only.
9: if (!InitializeCriticalSectionAndSpinCount(&CriticalSection,
10: 0x00000400) )
11: return;
12: ...
13:
14: // Release resources used by the critical section object.
15: DeleteCriticalSection(&CriticalSection);
16: }
17:
18: DWORD WINAPI ThreadProc( LPVOID lpParameter )
19: {
20: ...
21:
22: // Request ownership of the critical section.
23: EnterCriticalSection(&CriticalSection);
24:
25: // Access the shared resource.
26:
27: // Release ownership of the critical section.
28: LeaveCriticalSection(&CriticalSection);
29:
30: ...
31: return 1;
32: }
원문 : http://msdn.microsoft.com/en-us/library/ms683476(v=vs.85).aspx
Gems7권의 고성능 힙 관리자 예제가 컴파일이 안되는데 원인은 InitializeCriticalSectionAndSpinCount() 이 정의되있지 않다는 것이다.
1: #ifndef _HPHA_H_
2: #define _HPHA_H_
3:
4: #include <memory.h>
5: #include <string.h>
6: #include <assert.h>
7: #include <new>
8:
9:
10: #if defined(WIN32)
11:
12: #define _WIN32_WINNT 0x0501 // 추가해줌
13:
14: #ifndef WIN32_LEAN_AND_MEAN
15: #define WIN32_LEAN_AND_MEAN
16: #endif
17: #ifndef _WIN32_WINNT
18: #define _WIN32_WINNT WINVER
19: #endif
20: #include <windows.h>
21: #else
22: #error "Platform undefined or not supported"
23: #endif
winbase.h 에 InitializeCriticalSectionAndSpinCount()는 다음과 같이 선언되있다.
1: // winbase.h
2: #if (_WIN32_WINNT >= 0x0403)
3:
4: WINBASEAPI
5:
6: BOOL
7:
8: WINAPI
9:
10: InitializeCriticalSectionAndSpinCount(
11:
12: __out LPCRITICAL_SECTION lpCriticalSection,
13:
14: __in DWORD dwSpinCount
15:
16: );
17:
아래 포스트는 크리티컬섹션에 대한 간단한 클래스인데
InitializeCriticalSection 을 InitializeCriticalSectionAndSpinCount 으로 변경해줘야 memory oiut 에러가 나지 않음, 아래는 퍼온글
http://codemuri.tistory.com/20
크리티컬 섹션 초간단 클래스
class CCriticalSection
{
public:
void Lock() { EnterCriticalSection(&m_sec); }
void Unlock() { LeaveCriticalSection(&m_sec); }
CCriticalSection() { InitializeCriticalSection(&m_sec); }
~CCriticalSection() { DeleteCriticalSection(&m_sec); }
CRITICAL_SECTION m_sec;
};
출처가 MSDN이라 그냥 써도 될듯함.
From MSDN :
'운영체제 & 병렬처리 > Multithread' 카테고리의 다른 글
multi thread 를 이용한 로딩 화면 만들기 (0) | 2012.12.26 |
---|---|
[C++] 템플릿 기반 Critical Section 동기화 객체 (0) | 2012.12.24 |
CreateThread, _beginthread, _beginthreadex 에 대한 정리 (0) | 2012.12.23 |
쓰래드와 Sleep (0) | 2012.12.22 |
유저모드 동기화 , 인터락, 크리티컬 섹션 (0) | 2012.11.01 |