카테고리 없음

크리티컬 섹션, 뮤텍스, 세마포어

코코몹 2025. 6. 29. 14:33

목표

세 가지에 대해 명확히 구분해서 이해하기

 

기본 개념

Critical Section

개념

멀티스레드 또는 멀티프로세스 환경에서 여러 스레드나 프로세스가 동시에 접근해서는 안 되는 공유 자원을 다루는 코드의 특정 영역을 말함

 

주요 특징

특징 설명
상호 배제 크리티컬 섹션에서는 한 번에 오직 하나의 스레드 또는 프로세스만이 해당 코드 영역을 실행할 수 있도록 보장함
이를 통해 동시에 여러 스레드가 공유 자원에 접근하여 발생할 수 있는 충돌과 데이터 불일치를 방지함
동기화 메커니즘 크리티컬 섹션의 동시 접근을 막기 위해 뮤텍스(Mutex), 세마포어(Semaphore), 락(Lock) 등 다양한 동기화 기법이 사용됨
진입점과 출구점 크리티컬 섹션은 진입(Enter)과 출구(Exit) 지점이 명확하게 구분됨
공유 자원에 접근하려면 반드시 잠금을 획득해야 하며, 작업이 끝난 후에는 반드시 잠금을 반환해야 함
데이터 일관성 보장 크리티컬 섹션을 통해 공유 자원의 동시 접근을 제한함으로써 데이터의 무결성과 일관성을 유지할 수 있음

 

장단점

장점

구분 내용
데이터 무결성 보장 공유 자원에 대한 동시 접근을 차단하여 데이터 손상이나 불일치를 방지
코드 간소화 멀티스레드 환경에서 공유 자원 접근 로직을 명확히 구분해 프로그램의 예측 가능성을 높임
성능 향상 경합 조건 감소로 시스템 효율성을 개선할 수 있음
레거시 호환성 대부분의 운영체제와 프로그래밍 언어에서 널리 지원됨

 

단점

구분 내용
병목 현상 한 번에 하나의 스레드만 접근 허용
이로 인해 대기 시간이 증가할 수 있음
교착 상태 리스크 잘못된 설계 시 스레드가 서로의 자원을 무한히 기다리는 교착 상태(dead lock)가 발생할 수 있음
잠금 관리 오버헤드 잠금 획득/해제 과정에서 성능 저하가 발생할 수 있음
구현 복잡성 디버깅이 어렵고 오류 발생 시 원인 분석이 복잡함

 

사용시 주의사항

항목 내용
최소화 원칙 크리티컬 섹션 범위를 필요한 코드로 제한해 잠금 시간을 최소화함
락 경합 감소 자주 사용되지 않는 자원은 별도의 락을 사용하여 경합을 분산시킴
예외 안전성 보장 RAII(Resource Acquistion Is Initialization) 패턴 적용
초기화 스핀 카운트 설정으로 짧은 대기 시 커널 진입을 지연시켜 성능 향상
점유 시간 관리 크리티컬 섹션 점유 시간이 기본 타임아웃을 초과하면 예외가 발생하므로 장시간 점유를 피해야함
재진입성 고려 크리티컬 섹션 내부에서 블로킹 호출을 피해 재진입 문제를 방지함

 

Mutex

개념

상호 배제를 위한 동기화 메커니즘으로, 여러 스레드/프로세스가 공유 자원에 동시 접근하는 것을 방지함

한 번에 하나의 스레드만 Critical Section(임계 구역)에 진입할 수 있도록 제어하며, Data Race(데이터 경쟁)과 불일치를 방지함 

 

핵심 원리

원리 설명
Lock-Unlock 메커니즘 lock() : 스레드가 임계 구역 진입 전 뮤텍스 잠금 시도
- 성공 시 : 진입 및 작업 수행
- 실패 시 : 다른 스레드가 잠금 중이면 대기 상태로 전환
unlock() : 작업 완료 후 잠금 해제하여 대기 중인 스레드에 진입 권한 부여
소유권 뮤텍스를 잠근 스레드만이 해당 잠금을 해제할 수 있음
세마포어와 달리 자원 소유 책임이 명확함

 

주요 특징

특징 설명
이진 상태 잠금 해제와 잠금인 0과 1의 상태만 존재
커널 객체 프로세스 간 공유 가능
재진입 불가 동일 스레드가 중복 잠금 시 교착 상태 발생 가능
대기 함수 연동 (윈도우에서) WaitForSingleObject() 등과 결합해 비신호 상태에서 스레드 블로킹

 

장단점

장점

구분 내용
데이터 일관성 및 안정성 보장 한 번에 하나의 스레드/프로세스만 공유 자원에 접근할 수 있어 데이터 경쟁과 불일치 방지
사용 및 이해가 간단 기본적인 락/언락 구조로 동작 원리가 직관적이고 구현이 쉬움
단일 리소스 상호 배제에 최적 단일 자원에 대한 접근 제어에 매우 효과적임
데드락 가능성 상대적으로 적음 세마포어에 비해 구조가 단순해 데드락 발생 가능성이 낮음

단점

구분 내용
병목 및 성능 저하 한 번에 하나의 스레드만 접근 가능해 동시성 저하, 대기 기산 증가, 전체 처리량 감소
Deadlock 위험 여러 뮤텍스 사용 시 잠금 순서가 꼬이면 데드락이 발생할 수 있음
Starvation 현상 우선순위가 낮은 스레드가 계속 락을 얻지 못하고 대기할 수 있음
우선순위 역전 문제 낮은 우선순위 스레드가 락을 점유하면 높은 우선순위 스레드가 대기해야 하는 상황 발생
Busy Waiting 발생 가능 구현에 따라 락을 얻기 위해 CPU를 소모하며 반복 대기하는 busy wait 상태가 발생할 수 있음
컨텍스트 제한 락을 획득한 스레드/프로세스만 해제가 가능해, 다른 컨텍스트에서 언락이 불가능함

 

주의사항

주의사항 내용
Deadlock(교착 상태) 여러 뮤텍스 사용 시 잠근 순서 불일치로 발생 가능
성능 저하 빈번한 잠금/해제로 컨텍스트 스위칭이 증가하여 성능 저하 발생

 

Semaphore

개념

프로세스나 스레드가 세마포어의 값을 감소시키는 P연산(wait)를 통해 자원에 진입하고, 임계구역에서 작업 마치면 세마포어 값을 증가시키는 V연산(signal)을 통해 자원을 관리하는 동기화 기법

 

주요 특징

카운트 기반으로 여러 개의 자원을 동시에 관리할 수 있음

 

장단점

장점

항목 내용
동시성 제어  여러 프로세스/스레드가 제한된 자원을 효율적으로 공유할 수 있게 해줌
유연성 카운트 값을 조정해 여러 개의 자원을 동시에 관리할 수 있음
경쟁 조건 방지 임계 구역에 대한 동시 접근을 막아 데이터 손상이나 불일치를 예방함
데드락 방지 가능 자원 접근 순서를 제어해 교착 상태를 예방할 수 있음
프로세스/스레드 동기화 여러 프로세스나 스레드 간의 실행 순서 제어가 가능함

단점

항목 내용
Deadlock 잘못된 사용 시 둘 이상의 프로세스가 서로 자원을 기다리며 무한 대기 상태에 빠질 수 있음
Starvation 특정 프로세스가 자원을 계속 얻지 못하고 무한 대기할 수 있음
우선순위 역전 낮은 우선순위 프로세스가 자원을 점유해 높은 우선순위 프로세스가 대기할 수 있음
오버헤드 프로세스 상태 전환(ready↔block) 및 큐 관리 등으로 인한 시스템 자원 소모가 발생함
프로그래밍 복잡성 P/V 연산의 순서나 사용법을 잘못 적용하면 상호 배제 실패, 데드락 등 심각한 오류가 발생할 수 있음
경쟁 조건 완전 방지 불가 세마포어만으로 모든 경쟁 조건을 막을 수 있는 것은 아님

주의사항

주의사항 내용
연산 순서와 원자성 보장 P(Wait)와 V(Signal) 연산은 반드시 원자적으로 수행되어야함
문제 예시)
* P-임계구역-P와 같이 P 연산을 중복으로 사용하면 임계구역에서 빠져나올 수 없게 되어 교착상태 발생
* V-임계구역-P와 같이 잘못된 순서로 사용하면 여러 프로세스가 동시에 임계구역에 진입해 상호 배제가 깨질 수 있음
데드락 예방 자원 획득 순서가 꼬이면 데드락 발생 가능
임계구역 최소화 임계구역이 길어지면 시스템 성능이 저하되고, 대기하는 프로세스가 많아질 수 있음
Busy Waiting 피하기 Busy Waiting(계속 반복문을 돌며 대기) 발생 가능
-> Block-WakeUp 방식(대기 큐 사용)을 적용해 CPU 자원 낭비를 줄이는 것이 좋음
세마포어 값 및 자원 수 적절히 설정 과도한 세마포어 값 설정은 동시 접근으로 인한 데이터 손상 위험을 높이고, 너무 낮으면 병목 현상이 발생할 수 있음
오버헤드 및 성능 테스트 프로세스 상태 전환, 큐 관리 등으로 오버헤드가 발생할 수 있음
-> 적용 전 성능 테스트 수행 필요
기아와 우선순위 역전 방지 기아 현상, 우선순위 역전 문제 주의 필요

대기 성능 및 효율성 비교

기법별 비교

기법 대기 발생 시 특징 최적 사용 시나리오
크리티컬 섹션 커널 전환 없음 : 사용자 모드에서 작동해 대기 시 오버헤드 최소화 동일 프로세스 내 스레드간 빠른 동기화 필요시 사용
스레드 블로킹 : 운영체제가 스케줄링을 중지해 CPU 소모 없음
뮤텍스 커널 전환 필요 : 잠금/해제 시 컨텍스트 스위칭 발생하여 대기 시간 증가 프로세스 간 동기화 필요시 사용
우선순위 역전 위험 : 낮은 우선순위 스레드가 락 점유 시 대기 길어짐
세마포어 카운트 기반 대기 : 지정된 수만큼 동시 접근 허용해 대기 시간 분산 리소스 풀 관리
블로킹 최소화 : 여유 리소스 있으면 즉시 진입 가능

 

대기 시 가장 유리한 경우

기법 경우
크리티컬 섹션 단일 프로세스 내 고속 동기화가 필요한 경우
뮤텍스 제한된 리소스 풀 관리 시 효율적
세마포어 크로스 프로세스 공유 자원 보호 시 필수

최적화 전략

기법 전략
크티티컬 섹션 짧은 대기 시 스핀락 적용
뮤텍스 우선순위 상속 프로토콜로 우선순위 역전 방지
세마포어 try_wait 함수를 이용해 논블로킹 폴백 구현

 

코드 예시

 

플랫폼별 차이

구분 Critical Section Mutex Semaphore
정의 공유 자원에 대한 접근을 제한하는 코드 영역 상호 배제를 위한 동기화 객체 지정된 수만큼 동시 접근을 제어하는 동기화 객체
동시 범위 한 프로세스 내 스레드 간 동기화 여러 프로세스/스레드 간 동기화 가능 여러 프로세스/스레드 간 동기화 가능
동시 접근 1개 스레드만 허용 1개 스레드/프로세스만 허용 지정한 개수만큼 동시 접근 허용
구현 방식 사용자 객체(커널 진입 불필요, 빠름) 커널 객체(프로세스 간 공유 가능) 커널 객체(카운트로 동시 접근 제어)
주요 용도 한 프로세스 내 빠른 동기화 상호 배제, 프로세스/스레드 간 단일 접근 제어 동시성 제어, 리소스 개수 제한
특징 가볍고 빠르나, 프로세스 내부에서만 사용 소유권 개념(획득한 스레드만 해제 가능) 카운트 기반, 소유권 없음, 여러 개 동시 허용

핵심 차이 정리

  • 크리티컬 섹션 : 개념적으로 임계영역을 의미하거나, 한 프로세스 내에서만 동작하는 가벼운 동기화 기법
  • 뮤텍스 : 상호 배제만을 위한 커널 객체로, 여러 프로세스/스레드 간 단일 자원 접근을 엄격히 제어
  • 세마포어 : 카운트 기반으로 여러 개의 동시 접근을 허용하며, 뮤텍스보다 더 일반적인 동기화 기법임. 세마포어의 카운트가 1이면 뮤텍스와 동일하게 동작할 수 있음

 

추가 개념

 

RAII( Resource Acquistion Is Initialization)

개념

C++의 핵심 디자인 패턴으로, 자원의 수명을 객체의 수명에 바인딩하여 자동 관리하는 기법

 

핵심 원리

자원 획득 = 객체 초기화

자원 해제 = 객체 파괴

 

장점

예외 안정성 보장

코드 간소화

자원 누수 방지

오류 감소

 

e.g) 

class ScopedLock
{
public:
    ScopedLock(CRITICAL_SECTION& cs) : m_cs(cs)
    { 
        EnterCriticalSection(&m_cs);	// 잠금 획득 
    }
    ~ScopedLock()
    { 
        LeaveCriticalSection(&m_cs);	// 자동 해제 
    }
private:
    CRITICAL_SECTION& m_cs;
};

* 생성자에서 잠금을 획득하고, 소멸자에서 자동으로 해제되므로 예외 발생시에도 안전함