[OS] 세마포오 & 뮤텍스

업데이트:

세마포오(Semaphore) & 뮤텍스(Mutex)

공유된 자원에 여러 프로세스가 동시에 접근하면서 문제가 발생할 수 있다. 이때 공유된 자원의 데이터는 한 번에 하나의 프로세스만 접근할 수 있도록 제한을 둬야 한다.

이를 위해 나온 것이 바로 '세마포오''뮤텍스' 이다.

세마포오 : 멀티 프로그래밍 환경에서 공유 자원에 대한 접근을 제한하는 방법

뮤텍스 : 임계 구역을 가진 스레드들의 실행시간을 서로 겹치지 않고 각각 단독으로 실행되게 하는 기술 (Lock, Unlock 을 이용해서 한번에 하나의 스레드만 사용되도록 )

세마포오와 뮤텍스의 대한 설명을 들어가기 전에 알아야 할 개념은 임계구역(Critical Section) 이다.

Critical Section : 여러 프로세스가 데이터를 공유하며 수행될 때, 각 프로세스에서 공유 데이터를 접근하는 프로그램 코드 부분

공유 데이터를 여러 프로세스가 동시에 접근할 때 잘못된 결과를 만들 수 있기 때문에, 한 프로세스가 임계 구역을 수행할 떄는 다른 프로세스가 접근하지 못하도록 해야 한다.

세마포오

semaphore

세마포오에서는 다음과 같은 개념들이 포함된다.

P (wait) : 임계 구역 들어가기 전에 수행(프로세스 진입 여부를 자원의 개수(S)를 통해 결정)

V (signal) : 임계 구역에서 나올 떄 수행(자원 반납 알림, 대기 중인 프로세스를 깨우는 신호)

S : 동시 접근할 수 있는 프로세스(스레드) 갯수라고 생각하면 된다. 따라서 이 값이 1이면 Mutex랑 같은 효과를 낼 수 있다(이진세마포오). 그리고 S는 전역변수 이다.

이러한 P와 V를 구현해보면 다음과 같다.


P(S){ // -> 잔다는 개념
    while(S <= 0){ // S가 0 이하면 동작할 수 없기 때문에
        ; // busy waiting -> S가 0이 될때까지 무한 루프
    }
    S--;
}

V(S){
    S++; // 자원을 반납하면서 동작할 수있는 S카운트 값을 증가시켜 다른 프로세스(스레드)가 동작하도록 할 수 있다. -> 깨운다는 개념
}

이를 통해, 한 프로세스가 P 혹은 V를 수행하고 있는 동안 프로세스가 인터럽트 당하지 않게 된다. P와 V를 사용하여 임계 구역에 대한 상호배제 구현이 가능하게 되었다.

예시

  1. 먼저 도착한 A가 P(S)를 실행하여 S값을 0으로 만들고 임계구역으로 들어감
  2. 그 뒤에 도착한 B가 P(S)를 실행하지만 S가 0이기에 대기상태
  3. A가 임계구역 수행을 마치고 V(S)를 실행하면 S는 다시 ++됨
  4. B는 이제 P(S) 무한루프에서 빠져나올 수 있게 되고 임계구역 들어가서 수행

뮤텍스

뮤텍스는 임계구역 동시 접근을 통해 문제가 생기는 것을 막기 위해 Lock이란 개념을 사용한다.

Lock : 현재 임계 구역에 들어갈 권한을 얻어옴(만약 다른 프로세스/스레드가 임계 구역 수행 중이면 종료할 때까지 대기)

Unlock : 현재 임계 구역을 모두 사용했음을 알림(대기 중인 다른 프로세스/스레드가 임계 구역에 진입할 수 있음)

뮤텍스는 S값이 0,1인 이진 세마포오 라고 부르기도 함


while(1){
    acquire block
        critical section
    release block
        remainder section
}

acquire(){
    while(!available){ // 현재 어떤 프로세스가 점유하고 있다면 무한루프
        ; // busy waiting
    }
    available = false;
}

release(){
    available = true;
}

예시(OS 공룡책 참조)

#include stdio.h
#include pthread.h
int sum 0; // a shared variable
pthread_mutex_t mutex; 

void *counter (void *param)
{
    int k;
    for(k = 0; k < 10000; k++){ // 10000번 스레드
        // entry section
        pthread_mutex_lock(&mutex); // mutex lock
        // critical section
        sum++;
        // exit section
        pthread_mutex_unlock(&mutex);
        // remainder section
        pthread_exit(0)
    }
}

int main
{
    pthread_t tid1 tid2;
    pthread_mutex_init(&mutex, NULL);
    pthread_create(&tid1, NULL, counter, NULL); 
    pthread_create(&tid2, NULL, counter, NULL);
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    printf("sum == %d\n ",sum);
}

Summary

Critical Section이라는 공유 공간에 여러 프로세스들이 동시 접근하게 될 때 동기화란 개념이 들어가지 않는다면 문제가 생길 것이다. 그러한 것들을 해결하기 위한 동기화 방법 중 세마포오뮤텍스에 대해 알아 보았습니다.

각각 세부적인 내용을 깊게 들어간다면 너무 복잡해지기에 나중에 시간이 된다면 정리하겠습니다.

Reference

Gyoogle

댓글남기기