임계 영역 - 둘 이상의 쓰레드가 동시에 접근할 위험 요소를 가지고 있는 코드 블록


동시에 접근하는 것을 막는 것이 메모리 동기화


커널 쓰레드 동기화는 여러 기능이 있다. 심지어 프로세스 쓰레드간 동기화도 존재한다



예를 들어, A 와 B 라는 사람이 화장실 앞에서 마주쳤다.

A는 큰 일을 볼 사람이고, B 는 작은 일을 볼 사람이다.

이런 상황에서는, 보통 B 가 양보를 한다

그럼 B 는 이제 어떻게 할까!? 이것이 바로 순서가 무너진 상황이다.

쓰레드도 실행 순서가 중요한 경우가 있다.

만약, A 쓰레드가 계산하고, 그 결과를 B 쓰레드가 출력 한다고 할 때, 반드시 A 쓰레드가 먼저 실행되어야 한다.


실행 순서 동기화



한 순간에 하나의 쓰레드만 접근해야 하는 메모리 영역이 존재한다.

대표적으로 데이터 영역과 힙 영역이다.

앞서 _beginthreadex 함수를 소개하며, 메모리에 동시 접근할 때 어떤 문제가 생기는지 설명했다.

즉, 이렇게 메모리 접근에 있어서 동시 접근을 막는 것 또한 쓰레드의 동기화에 해당한다.

위의 것의 차이점을 보자.

실행 순서의 동기화는, 이미 순서가 정해져 있는 상황인 반면에, 메모리 접근의 동기화는, 실행 순서가 중요한 것이 아니라 한 순간에 하나의 쓰레드만 접근하면 되는 상황이다.


Windows 에서 제공하는 동기화 기법은 제공하는 주체에 따라 크게 두 가지로 나뉘는데, 하나는 유저 모드 동기화 기법이고, 또 하나는 커널 모드 동기화 기법이다.

유저 모드 동기화

동기화 과정에서 커널의 코드를 사용하지 않는 동기화 기법이다.

따라서 커널 모드로의 전환이 불필요하므로 성능상 이점이 있지만, 그 만큼 기능상 제한이 있다.

커널 모드 동기화

커널에서 제공하는 동기화 기능을 활용하는 것이다.

동기화 관련 함수가 호출될 때 마다 커널 모드로의 변경이 필요하고, 때문에 성능의 저하가 있다.

하지만 그 만큼 유저모드 동기화에 비해 기능이 많다.


굳이 크리티컬섹션 함수 안에 어떻게 구현이 되어 있는지 알아볼 생각은 하지 말고 주어진걸 쓸 생각 하라고 하네


그리고 임계영역 구성은 최소한의 부분만!


인터락 함수(Interlocked Family Of Function) 기반의 동기화


앞의 예제처럼, 전역으로 선언된 변수 하나의 접근 방식을 동기화 하는 것이 목적이라면, 인터락 함수도 괜찮다.

인터락 함수는 내부적으로 한 순간에 하나의 쓰레드에 의해서만 실행되도록 동기화 되어있다.

LONG InterlockedIncrement(LONG volatile* Addend);

이 함수의  인자는, 값을 하나 증가 시킬 32비트 변수의 주소값을 전달한다.

둘 이상의 쓰레드가 공유하는 메모리에 저장된 값을 이 함수를 통해 증가시킬 경우, 동기화 된 상태에서 접근하는 것과 동일한 안정성을 보장받을 수 있다.

LONG InterlockedDecrement(LONG volatile* Addend);

둘 이상의 쓰레드가 공유하는 메모리에 저장된 값을 이 함수를 통해 증가시킬 경우, 동기화 된 상태에서 접근하는 것과 동일한 안정성을 보장받을 수 있다.

위 함수들은, 한 순간에 하나의 쓰레드만 접근하는 것을 보장하는 함수이다.

따라서, 이 함수를 사용할 시 동시에 둘 이상의 쓰레드 접근에 의한 문제는 결코 없다.

앞의 크리티컬 섹션 동기화 기법도 내부적으로는 인터락 함수 기반이다.

이러한 함수들도 유저 모드 기반이므로, 속도는 상당히 빠르다.


크리티컬섹션 작동 방식은


인터럽트를 막아버리는 방식으로 구현할 수도 있다.


하드웨어가 운영체제에 시간을 보내주는 것을 인터럽트로 알려주는데 이 때 인터럽트를 막아버려서 시간을 알려주지 않으면 임계영역을 신나서 동작시킨다는 것




커널 모드 동기화

뮤텍스는 세마포어의 일부다



뮤텍스는 키가 1개다



세마포어는 키가 여러개다



A쓰레드가 키를 가지고 정상 반환을 하지 못했을 때, 윈도우는 그 코드를 받아서 바로 앞에서 대기중이던 B쓰레드에 쥐어준다.


열쇠 소유의 개념이 있기 때문에 가능한 것이다.


하지만 세마포어는 키가 여러개고, 키를 어떤 쓰레드가 가져갈지 모르기 때문에 소유의 개념이 없다.


그래서 위와 같은 예외처리가 불가능하다.


그렇다

+ Recent posts