[시스템] 뮤텍스와 바이너리 세마포의 차이점

@codemaru · July 05, 2007 · 6 min read

Windows에는 스레드를 동기화할 수 있는 다양한 커널 객체가 있다. 이벤트, 타이머, 세마포, 뮤텍스가 그것이다. 이중에서 신입 개발자를 가장 헷갈리게 만드는 것은 뮤텍스와 세마포다. 이론적으론 뮤텍스와 바이너리 세마포는 동일한 기능을 하기 때문이다. 서로 다른 스레드가 객체에 동시에 접근할 수 없도록 하는 것이 주된 기능이다. 하지만 늘 이론은 이론이다. 실제 Windows에 구현된 이 두 객체는 조금 다른 특징을 가지고 있다.

이 둘의 가장 큰 차이는 소유권이다. 뮤텍스의 경우 커널 객체중 유일하게 소유권 개념을 가지고 있다. 다른 모든 커널 객체는 소유권 개념이 없다. 소유권이란 해당 커널 객체가 자신을 소유하고 있는 스레드 정보를 저장하고 있는 것이다. 동기화 객체의 경우 소유한다는 의미는 WaitForSingleObject를 통해서 진입에 성공했다는 것이다. 해당 함수를 통해서 뮤텍스나, 세마포를 소유한 경우 ReleaseMutex나 ReleaseSemaphore를 호출하기 전까지는 해당 스레드가 객체를 소유하고 있는 것이다.

간단한 상황을 한번 생각해 보자. A, B 두 개의 스레드가 있고, 동기화를 위해 뮤텍스나 세마포를 사용해야 하는 상황이다. A 스레드가 WaitForSingleObject를 통해서 먼저 객체를 소유했다고 가정해 보자. 그렇다면 이 상황에서 B 스레드가 ReleaseMutex나 ReleaseSemaphore를 통해서 소유된 해당 객체를 해제하려는 시도를 하면 어떻게 될까? 여기서 뮤텍스와 세마포의 차이가 나타난다. 뮤텍스의 경우는 소유권을 저장하고 있기 때문에 FALSE를 리턴한다. 그리고 GetLastError값으로 해당 커널 오브젝트의 소유권을 ReleaseMutex를 호출한 스레드가 가지고 있지 않다는 것으로 설정한다(ERROR_NOT_OWNER). 반면 세마포는 합법적으로 해당 요구를 처리한다.

소유권은 위와 같은 보안상의 장점을 가지고 있지만 해제되지 않은 뮤텍스의 소유권과 관련된 새로운 문제를 야기 시킨다. 한 스레드가 뮤텍스를 소유한 다음 해당 뮤텍스를 해제하지 않은 상태에서 종료한 경우에 뮤텍스의 소유권을 어떻게 처리해야 할까? 개념적으론 다른 모든 스레드는 소유권이 없기 때문에 해당 뮤텍스를 획득할 수도 해제할 수도 없다. 즉, 해당 객체를 대기하고 있는 모든 스레드가 데드락 상황에 빠지는 것이다. 하지만 Windows는 이렇게 심각한 문제가 발생하도록 방치하진 않는다. 모든 커널 오브젝트를 직접 관리하기 때문에 해제되지 않은 뮤텍스가 있는지 검사해서 있다면 해당 뮤텍스를 해제한 다음 다른 스레드로 제어권을 넘겨준다. 이 경우에 뮤텍스의 소유권이 커널에 의해 강제적으로 이동된 것이기 때문에 그것을 알리기 위해서 WaitForSingleObject는 WAIT_OBJECT_0을 리턴 하지 않고 WAIT_ABANDONED를 리턴 한다. 반면 세마포의 경우 소유권 개념이 없기 때문에 이러한 문제가 발생하지 않는다.

소유권 문제의 경우 커널이 직접 제어해주기 때문에 일견 문제가 없는 것처럼 보이기도 한다. 하지만 이러한 처리가 즉시 일어나지 않는다는 점이 중요하다. 실제로 후킹 프로그램등에서 뮤텍스를 통해서 동기화를 하고 프로세스를 강제로 종료시켜 해당 뮤텍스가 해제되지 않은 상황에서 종료되도록 만든 경우를 살펴보면 문제의 심각성을 알 수 있다. 이 상황이 되면 시스템에 따라서 몇 분에서 어떤 경우에는 재부팅을 하기 전까지 해당 뮤텍스를 그 누구도 획득하지 못하는 일이 발생한다.

그렇다면 어떤 경우에 뮤텍스를 사용하는 것이 좋을까? 필자의 경우는 객체를 소유하는 시간과 객체의 사용 범위를 기준으로 결정한다. 객체를 소유하는 시간이 짧고, 객체의 사용 범위가 좁을수록 위에서 언급한 소유권 문제가 발생할 확률이 낮아지기 때문이다. 반면 객체를 소유하는 시간이 길고(사용자의 입력이 있을 때까지 대기하는 경우), 사용 범위가 넓은(여러 프로세스에서 공유되어 사용되는 경우) 경우에는 소유권 문제는 늘 발생할 수 있음을 명심해야 한다.

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중