프로그래밍에서 동기화가 필요한 경우는 매우 다양하다.

컴퓨터에서 자원이라 함은 주로 cpu나 메모리를 의미하는데 연산에 직접적으로 관여하는 부품을 말한다. 주변 정보기기와 통신하기 위한 인터럽트나 I/O 번지도 굳이 따지면 자원으로 분류된다. 그런데 이런 자원은 늘 제한되는 특성을 갖는다. 반면에 시스템은 여러 프로세스를 동시에 실행하여 운영하게 되면서, 각각의 프로세스는 저마다의 코드에 따라 특정 자원을 점유하려는 시도를 끊임없이 하게 된다. 이런 시도를 조정할 관리 시스템이 없다면 프로세스간의 충돌이 있을것이다.


지금부터 나오는 내용은 이런 구조적인 문제를 해결하기 위해 운영체제에 도입된 객체를 활용하는 방법이다.

운영체제가 제공하는 동기화용 커널객체에는 뮤텍스, 세마포어, 이벤트 등이 있다. 사용자 모드 동기화 객체로는 크리티컬 색션이 있다.




크리티컬 섹션(Critical Section)


- 한 시스탬 내에서 여러 스레드가 실행 중이라고 하더라도 실제로 CPU를 점유하여 연산을 하는 스레드는 하나이다. 코어가 두개라면 두 스레드가, 네 개라면 네 스레드가 동시에 실행 중일수 있다. 여러 스레드는 운영체제가 정하는 스케쥴에 따라 컨텍스트 스위칭을 하면서 실행된다는 것이 더 중요하다. 


- 크리티컬 섹션 객체로 보호하는 대상은 주로 전역 객체이다. 그중에서도 메모리와 관련된 대상은 반드시 그렇게 해야 멀티스레드 환경에서 문제가 되지 않는다.




뮤텍스와 데드락(Mutex Dead-lock)


- CMutex 클래스는 커널 뮤텍스를 객체화한 MFC클래스이다. 스레드와 프로세스를 동기화 시키는데도 사용한다. 일반적으로 스레드를 동기화 시킬때에는 뮤텍스가 아니라 크리티컬 섹션을 사용할 것을 권장한다. 이유는 뮤텍스가 동기화를 하는데 드는 비용이 크리티컬 섹션에 비해 크기 때문이다. 그렇다고 체감하기는 어렵지만 효율적으로 프로그래밍 하려면 고려해야하는 영역이다.


- CCriticalSection class나 CMutex class 모두 CSyncObject class의 파생 클래스인데 이들 클래스가 Lock()과 Unlock()메서드를 가상 함수로 정의한다. 

- CCriticalSection 에서는 인자값으로 주어지는 시간이 무시 되지만 CMutex 클래스에서는 이값이 적용되는데 여기서 시간은 멀티스레드 환겨에서 특정 스레드의 코드가 안전하게 주어지면 100mx 동안 다른 스레드의 저근이 차단되고, 100ms 이후에는 Unlock() 함수를 호출하지 않아도 자동으로 Lock() 함수가 풀리도록 한다. 이와 같은 기능이 필요한 이유는 데드락을 방지하기 위해서이다.


- 데드락은 스레드간의 서로 특정 자원을 점유한 상태에서 Lock() 함수를 호출하여 다른 스레드의 접근을 차단했지만 내부 코드사에서 조건이 맞지 않아서 Unlock() 함수를 호출하지 못하고 모든 스레드의 흐름이 정지된 상태를 말한다.


- Lock()함수에 시간값 인자를 줌으로써 데드락을 피해 특수한 상황에서도 스레드가 특정 코드나 자원으 무한저응로 점유하지 못하게 할수 있는것이다.



세마포어(Semaphore)


- 세마포어는 크리티컬 섹션이나 뮤텍스가 한 번에 한 스레드나 프로세스만 특정 리소스에 접근할 수있었던 것과달리동시에 여러 스레드나 프로세스가 특정 리소스에 접근할수 있도록 임의로 허용치를 정할 수 있다. 만일 10개의 스레드가 동시에 실행되는 멀티스레드 시스템에서 3개의 스레드만 리소스에 동시 접근이 가능하다면 일럴때 적합한 동기화 객체가 바로 세마포어이다.


- 서버 응용 프로그램에서 이런 구조가 절시하게 필요하다. 만일 동시에 최대 1000명까지 처리하는 서버가 있다고가정할대 일반 서비스의 경우에는 1000명 클라이언트 모두에게 서비스가가능하지만 특정 서비스만큼은 동시 접속을 10명까지로 서시브 제한을 두어야할 수도 있다. 이럴 경우에는 세마포어는 최선의 동기화 방법이 된다.


다음에 이벤트 방식의 동기화 방법에 설명하겠다.


+ Recent posts