2015. 1. 27.

[OS]임계영역(Critical Section) 접근 동기화1 - critical section 기반의 동기화 기법

 쓰레드임계영역을 통해서 쓰레드가 메모리 영역을 어떻게 공유하는지, 공유한 메모리에 동시 접근할 수 있기 때문에 발생할 수 있는 잠재적인 문제에 대해서 알아보았다.

 이를 바탕으로 임계영역의 동시접근을 막는 방법들을 알아보고자 한다.
 참고로 아래의 내용은 WIndows system을 기반으로 설명하고 있다.

임계영역과 동기화

 흔기 동기화라고 그러면 어떤 것들을 일치시켜주는 것을 의미한다. 클라우드와 로컬 저장소 사이의 동기화가 실행되면 클라우드에 저장된 데이터와 로컬 저장소에 저장된 데이터가 일치하지 않는가. 그런데 여기서 동기화는 조금 다른 의미를 지니고 있다. 일치한다는 의미가 아니라 순서에 있어서 질서가 잘 지켜지고 있다는 의미이다.

 질서가 잘 지켜지고 있다는 말은 임계영역에 접근하는 쓰레드의 순서가 잘 지켜진다는 것을 뜻한다. 동시접근하면 발생하는 문제를 예방하기 위해 동시접근을 예방하는 동시에 한 번에 하나의 쓰레드만 임계영역에 접근할 수 있다록 하는 것이 바로 임계영역 접근 동기화이다.


<출처: 윤성우 저, '윈도우즈 시스템 프로그래밍'>

 위의 코드는 전역변수를 선언하였고, 쓰레드들이 그 전역변수에 임의로 접근하는 코드이다. 전에도 말했지만 쓰레드의 실행순서를 예측하는 것은 불가능하다. ResumeThread() 함수를 통해 hThread[0] ~ hThread[5]를 거의 동시에 실행시키므로, IncreaseCount() 함수 내부의 gTotalCount에 하나씩 차례대로 접근할 것이라고 오해해서는 안된다. 쓰레드는 공유하는 메모리 영역에 자유롭게 접근할 수 있기 때문이다. 우리는 total count가 6000이 나올 것이라고 예상하지만, 6000이 나오지 않을 수도 있다.


임계영역에 대한 간단한 이해


 임계영역에 접근하려는 3개의 쓰레드가 있다. 고양이가 바로 쓰레드이다. 



 3개의 쓰레드들이 동시에 임계영역에 접근하려고 한다. 하지만 이는 알고 있듯이 문제가 발생한다. 그래서 하나의 쓰레드만 임계영역에 접근할 수 있다. 하나의 쓰레드가 임계영역에 진입하면 다른 쓰레드들은 기다린다. 위 그림에서는 쓰레드들이 잠을 자는 것으로 그려놓았는데, 실제로 BLOCK 상태가 된다. 



 먼저 들어간 쓰레드가 임계영역을 빠져나오면, 잠자던(BLOCK 상태) 쓰레드 중에 한  쓰레드가 임계영역에 진입할 수 있다. 진입하지 못한 쓰레드는 계속 잠을 자게 된다.

 대략적으로 임계영역을 동기화 하는 방법을 알았다. 이제 코드에 적용해보자.


임계영역 기반의 동기화 기법

 critical section은 임계영역을 나타내는 용어인 'critical section'를 그대로 기법의 이름으로 사용하였다.

 먼저 critical section 기반의 동기화 기법을 사용한 코드를 보자.


<출처: 윤성우 저, '윈도우즈 시스템 프로그래밍'>

 EnterCriticalSection() 함수와 LeaveCriticalSection() 함수를 이해하면 critical section 기반의 동기화 기법은 끝난다. 먼저 EnterCriticalSection() 함수는 인자로 CRITICAL_SECTION의 핸들(handle)을 사용한다.

 옷가게의 fitting room을 떠올려보자. 내가 옷을 골라서 갈아입기 위해 fitting room에 들어가려고 한다. 하지만 이미 fitting room을 사용하는 사람이 있다. '사용중'이라는 표시가 보인다. 그러면 나는 fitting room을 사용할 수 없고, 지금 사용 중인 사람이 사용을 마치기를 기다려야 한다. 그 사람이 사용을 마치고 나오면 이제 내가 사용할 수 있다. 내가 fitting room에 들어가는 동시에 fitting room은 다시 '사용중' 상태가 된다.

 임계영역이 바로 fitting room에 해당하고, critical section 기반의 동기화 기법이 바로 '사용중'을 표시해서 다른 이들이 fitting room에 두 명이 동시에 들어가는 것을 막는 방법이다.

 한 쓰레드가 EnterCriticalSection() 함수를 실행하면 fitting room에 들어가 사용 중이라는 선언한다. 그러면 다른 thread에 의해 EnterCriticalSection() 함수가 호출되면 이미 fitting room이 사용 중이기 때문에 이 쓰레드는 BLOCK 상태가 된다. 만약 fitting room을 사용 중인 쓰레드가 사용을 마치면 BLOCK 상태의 쓰레드가 비로소 BLOCK 상태에서 빠져나와 fitting room에 들어가 사용할 수 있다.

 LeaveCriticalSection() 함수는 어떤 쓰레드가 fitting room을 빠져나올 때, 다른 쓰레드들이 fitting room을 사용할 수 있도록 해주기 위한 함수이다. fitting room 사용을 마치고 LeaveCriticalSection() 함수를 호출하면, EnterCriticalSection() 함수를 호출했다가 BLOCK 상태가 된 쓰레드가 있다면 그 쓰레드는 BLOCK 상태에서 빠져나와서 임계영역에 진입하게 된다.

 정리하면 이 기법은 임계영역에 한 쓰레드만 진입할 수 있도록 다른 쓰레드를 BLOCK 상태로 만든다. 그리고 한 쓰레드가 임계영역을 빠져나오면 다른 쓰레드가 BLOCK 상태에서 빠져나와 임계영역에 진입한다.

댓글 없음:

댓글 쓰기