2 minute read

윈도우의 프로세스와 스레드 (5)

스레드 동기방법

스레드 상호간 리소스를 적절하게 분배하기 위해서 사용하는 이작업은 크게 몇가지로 나뉩니다.

가장 많이 사용하는것은 크리티컬 섹션과 세마포어, 모니터, 이벤트 등입니다.

다음은 WIN32 에서 사용하고있는 동기 요소 입니다.

동시 요소들은 커널 객체인 경우와 그렇지 않은 경우들이 있습니다. 커널 객체인경우 핸들을 사용하고 참조 숫자를 지정할수있는

특성이 있습니다.

1. 크리티컬 섹션

스레드로 부터 리소스 일부를 보호하는 기법으로 하나의 스레드가 어떤 리소스를 점유하겠다고 예약하는 기법입니다.

예약된 리소스는 예약된 스레드가 놓아주지않는 한 다른 스레드가 점유하지못합니다.

2. 뮤택스

커널 객체로 운영되기때문에 핸들을 사용할수 있습니다. 크리티컬 섹션이 가지는 교착상태문제를 해결할수있는 방법입니다.

다른 멀티 스레딩을 지원하는 언어에서 언급하는 모니터는 윈도우에서 뮤텍스의 일종입니다.

3. 세라포어

이 역시 커널 객체 이며, 뮤텍스가 단일 스레드를 기준으로 한다면 세라포어는 스레드의 수를 컨트롤할수있는 방법입니다.

4. 이벤트

범용적으로 쓰일수있는 방법, 신호에 의존하게 됩니다.

대기 타이머

스레드가 특정시간에 도달되었는지 파악, 엄밀하게 말해 동기 기능은 거의 존재하지않는다고 보아도 좋습니다.

선택지

크리티컬 섹션은 커널 객체가 아니므로 수행성능이 좋을수밖에 없습니다.

커널 객체를 사용하는 뮤택스나 세라모어는 객체 관리자와 연관지어 움직이기 때문에 커널이 참조 숫자를 일일이 관리하게 됩니다.

따라서 전반적으로 오버헤드가 걸리게됩니다. 같은 프로그램을 크리티컬 섹션으로 처리할것인지 뮤텍스나 세라포어로 처리할것인지 판단은

전적으로 교착상태가 발생할 가능성이 있는지에 달려있습니다.

만약 극히 적은확률로 교착상태가 발생할수있다면 크리티컬 섹션은 사용할수없습니다.

크리티컬 섹션

크리티컬 섹션은 열차의 화장실과 비슷합니다.

열차 화장실은 누가 들어가면 화장실 사용중이라고 켜지고 그 등이 꺼지기 전까지는 아무도 화장실에 들어가지 않습니다.

이와같이 화장실용 전등을 지칭하는 구조체 하나만을 더 만들어주면 됩니다.

크리티컬 섹션이 따로 들어간다고 해도 프로그램의 구조가 많이 변하는것은 아닙니다.

열차 화장실에 등을 달기위해서는 문고리에 스위치를, 외부에 등을 달면됩니다. 다만 화장실에 누가 들어간것을

감지해야 하므로, 들어간 즉시 문에 있는 스위치를 건들이도록 조정해야합니다.

크리티컬섹션은 하나의 구조체 CRITICAL_SECTION 을 사용하며, 다행히도 이 내부사정을 별로 알아야 될 필요성은 없습니다.

이 구조체의 주소는 다른 스레드로 부터 보호되는것들이 삽입되어있다는 사실을 알려줍니다.

커널 오브젝트가 아니라서 핸들에 의해 구현되는것이 아니라 직접 메모리 주소로 구분하게 됩니다.

크리티컬 섹션으로 Race Condition 을 해결했다고 생각할수도 있지만, 잘못하여 새로운 문제를 야기할수도 있습니다.

앞선 열차 화장실 문제에서 이미 드러난 것처럼, 누군가가 화장실을 점유하고 있다면 열차내에 있는 사람은 아무도 화장실에 가지못하는

일이 벌어집니다.

즉 보편적으로 멀티스레드 프로그램은 효율성을 나타내기 위해 운영되지만, 크리티컬 섹션을 잘못사용하면 프로그램이 정지하여 아무일도 하지못하는 상태가 될수있습니다.

이것은 일종은 교착상태인데, 다음 두가지로 나눌수있습니다.

  • 프로그램의 수행이 너무 길어지거나 다른 문제로 종료 하지 않는경우

  • 스레드가 중간에 예외를 발생시켜 미처 크리티컬 섹션을 빠져나오지 못한상태에서 스레드가 종료되는 바람에 시스템은 해당자원이 점유되고있다고 착각하는 경우

첫번째경우는 사실 크리티컬섹션으로 해결이 어렵기때문에 뮤택스나 세마포어를 도입합니다.

뮤택스의 경우 해당자원을 사용하기위해서 보호되는 영역으로 진입하려고 얼마나 기다려야 적절한지 시간계산이 가능하기 때문에 해당 문제를 해결할수있습니다.

일정시간을 기다려서 열차 화장실을 계속 점유하고있다면 누군가 화장실에 쓰러져있을가능성이 높으므로 119에 연락하게됩니다.

세라포어를 도입하는 경우는 버스 승강장 같은 경우 입니다.

출근 시간에 버스승강장은 매우 혼잡하지만, 승강장이 하나밖에 없다고 가정할때, 가장 좋은 해결책은 승강장을 몇개 더 만든느것입니다.

물론 세마포어가 무작정 많이 만든다고해서 효율적이고 좋은것은 아닙니다.

세마포어는 스레드 동기를 위한 커널객체중 가장 느린 상황이며 예외적인 상황이긴하지만 전체 세마포어 모두 시간지연이 벌어지는 경우가 많습니다.

크리티컬 섹션의 취약점은 스레드가 중간에 죽어버린경우에 종종발생합니다.

시스템이 예외상황을 맞아서 스레드만 종료된경우 시스템은 해당 스레드가 점유중이라고 판단하고 다른 스레드의 진입을 막습니다.

따라서 크리티컬 섹션으로 진입하는 경우 반드시 예외처리를 해야합니다.

Reference

https://karfn84.tistory.com/entry/%ED%8E%8C%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%9C%88%EB%8F%84%EC%9A%B0%EC%9D%98-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A0%88%EB%93%9C

Categories:

Updated: