관리 메뉴

드럼치는 프로그래머

[TCP/IP] 임계영역 (Critical Section) 본문

★─Programing/☆─TCP IP

[TCP/IP] 임계영역 (Critical Section)

드럼치는한동이 2008. 4. 28. 12:47

다음과 같은 동기화 되지 않은 쓰레드 코드가 있다고 가정해보자

int suInt[100];

DWORD WINAPI MyThread_1(LPVOID arg)
{
   for (int i=0; i<100; i++)
  {
      suInt[i] = 1;
      Sleep(10);
   }

   return 0;
}

DWORD WINAPI MyThread_2(LPVOID arg)
{
   for (int i=98; i>=0; i--)
   {
      suInt[i] = 2;
      Sleep(10);
   }

   return 0;
}

void main()
{
    HANDLE hThread[2];
    DWORD ThreadId[2];

    hThread[0] = CreateThread(NULL,0,MyThread_1,NULL,0,&ThreadId[0]);
    hThread[1] = CreateThread(NULL,0,MyThread_2,NULL,0,&ThreadId[1]);
   
    for(int i=0; i<100; i++)
           cout << suInt[i] <<" ";
}


의도한 결과값은 2가 98번 나오고 1이 1번 출력이 되어야 한다.

하지만 막상 실행해보면 2와 1이 불규칙적으로 출력이 된다.

쓰레드 1,2가 공유자원 suInt에 불규칙적으로 접근했기 떄문에 데이터가

의도되지 않게 입력 되었다.


임계영역은 두개 이상의 쓰레드가 공유리소스를 접근할 때 오직 한 쓰레드만

접근을 해야 하는 경우에 사용한다.


  임계영역은 유저영역 메모리에 존재하는 구조체다. 따라서 다른 프로세스가

      접근 할 수 없으므로,한 프로세스에 속한 동기화에만 사용 할 수 있다.

   일반적인 동기화 객체보다 빠르다.


임계영역을 사용하여 수정한 코드

CRITICAL SECTION cs; //임계영역 설정

DWORD WINAPI MyThread_1(LPVOID arg)

{
   //이 영역안에서 공유자원에 접근 할 경우 다른쓰레드가 침범하지 못한다
  EnterCriticalSection(&cs);  

   for (int i=0; i<100; i++)
   {
      suInt[i] = 1;
      Sleep(10);
   }

   LeaveCriticalSection(&cs);

   return 0;

}

DWORD WINAPI MyThread_2(LPVOID arg)
{
   EnterCriticalSection(&cs);

   for (int i=98; i>=0; i--)
   {
      suInt[i] = 2;
      Sleep(10);
   }

   LeaveCriticalSection(&cs);

   return 0;
}

void main()
{
    InitializeCriticalSection(&cs); //임계영역 초기화

    HANDLE hThread[2];
    DWORD ThreadId[2];

    hThread[0] = CreateThread(NULL,0,MyThread_1,NULL,0,&ThreadId[0]);
    hThread[1] = CreateThread(NULL,0,MyThread_2,NULL,0,&ThreadId[1]);

   WaitForMultipleObjects(2,hThread,TRUE,INFINITE); //쓰레드 종료대기

   DeleteCriticalSection(&cs); //임계영역 제거

   for(int i=0; i<100; i++)
     cout << suInt[i] <<" ";
}

Comments