2008. 10. 3. 22:20

[강의정리] 4가지 동기화 기법

출처 : 신경준씨 사외교육 http://blog.naver.com/process3/20052147545




-> Critical section이 Mutex보다 속도가 10배정도 빠르다.

    Critical section는 유저모드에서 작동하는 obj이기 때문이며 같은 프로세스안에서만 사용이

    가능하다.

 

   - 두개의 Critical section을 돌려도 Mutex보다 빠르다. Critical section은 Count만을 가지고

     있으며 Mutex는 커널까지 내려가서 Critical영역에 대한 관리를 요청하기 때문에 느릴 수 밖에

     없다.

 

   - 반면에 다른 프로세스에서 다른 프로세스의 자원을 사용할 때는 Mutex를 사용할 수 밖에 없다.

 

   - 정리하자면 Critical section은 같은 프로세스내에서의 임계영역(Critical 영역)을 관리 한다.

      (위의 머리말 의미와 동일)

 

-> 코드2듀오 일때 spinCount를 쓰는 것이 5%정도 더 성능이 올라간다.

 

-> Critical section내에는 sleep를 쓰지 않는 것을 기본으로 하는데 그대신 이벤트처리를

    해도 된다.

 

[ 세마포어 ]

 

-> 예제 소스

 

#include "stdafx.h"
#include
#include "process.h"

#define THREAD_NUM 10
#define INIT_COUNT 0
#define TOTAL_COUNT 10
#define RELEASE_COUNT 1


int g_nIndex = 0;

typedef struct msg_block_tag
{
 HANDLE    hSemaphore; 
} THREAD_ARG;

void PrintTrace()
{
 _tprintf(_T("Thread Exit ID = %d|%0x \n"), g_nIndex, GetThreadId(GetCurrentThread()));
 g_nIndex++;
}

unsigned int WINAPI TestThread(LPVOID lpThreadData);

int _tmain(int argc, _TCHAR* argv[])
{
 unsigned int unThreadId = 0;
 THREAD_ARG  stThreadArg;
 int    i = 0;
 HANDLE   hThread[THREAD_NUM] = {NULL};
 LONG   lPreviousCount = 0;

 stThreadArg.hSemaphore = CreateSemaphore(NULL, INIT_COUNT, TOTAL_COUNT, NULL);

 for( i = 0; i < THREAD_NUM; i++)
 {
  hThread[i] = (HANDLE)_beginthreadex(NULL, 0, TestThread, &stThreadArg, 0, &unThreadId);
 }

 ReleaseSemaphore(stThreadArg.hSemaphore, RELEASE_COUNT, &lPreviousCount );

 WaitForMultipleObjects(THREAD_NUM, hThread, TRUE, INFINITE);
 
 for( i = 0; i < THREAD_NUM; i++)
 {
  CloseHandle(hThread[i]);
  hThread[i] = NULL;
 }

 CloseHandle(stThreadArg.hSemaphore);
 stThreadArg.hSemaphore = NULL;

 return 0;
}

 

unsigned int WINAPI TestThread(LPVOID lpThreadData)
{

 THREAD_ARG *lpArg = (THREAD_ARG*)lpThreadData;
 DWORD  dwThreadStatus = 0;
 LONG  lPreviousCount = 0;

 while(TRUE)
 {
  dwThreadStatus = WaitForSingleObject(lpArg->hSemaphore, INFINITE);
 
  }
 }

return 0;

}

 

-> 세마포어의 큰 장점은 숫자를 이용할 수 있어 자기가 원하는 쓰레드 수를 고를 수 있다는 점이다.

    - 소스를 보면 10개의 쓰레드가 모두 wait상태에서 있다가 하나가 벗어나면

      ReleaseSemaphore를  하여 다음 쓰레드에게 알려주게 된다.

 

    - 세마포어의 ReleaseCount를 1로 하면 Mutex와 똑같이 작동을 한다.

 

    - 웹 서버개발시 Mutex와 세마포어를 같이 사용할 수도 있다.

      ex) 80개의 쓰레드가 있을 때 Mutex를 쓰면 1개씩 작동을 하므로 나머지 79개가 서로 경쟁

           을 하게 되어 비효율적이다. 그러므로 CPU가 8개라면 세마포어를 이용하여 ReleaseCount

           를 8개로 주고 Mutex를 이용하여 그 8개끼리 경쟁을 하게 하면 더욱더 효율적으로

           구현할 수 있다.( 강의 PPT 15번 참조 )

 

     - 강의 PPT 15번 내용

 

---------------------------------------------------------------------------------------- 

Semaphore Throttles (Thundering Herd(놀란 양떼))

 하나의 동기화 객체(크리티컬 섹션 또는 뮤텍스)를 기다리는 스레드가

너무 많은 경우, 세마포어를 하나 더 둬서, 해당 동기화 객체를 기다리는

스레드의 숫자를 줄여주는 것이 성능 향상에 도움이 된다.

while (TRUE) { // Worker loop
  
WaitForSingleObject (hThrottleSem, INFINITE);
  
WaitForSingleObject (hMutex, INFINITE);
      ... Synchronization code  ...
  
ReleaseMutex (hMutex);
  
ReleaseSemaphore (hThrottleSem, 1, NULL);
} // End of worker loop

 

----------------------------------------------------------------------------------------