[CS 기초 - 운영체제] 세마포어(Semaphore), 뮤텍스(Mutex), 스핀락(Spin lock)

deannn.Park·2021년 10월 25일
2

CS 기초

목록 보기
2/17
post-thumbnail
post-custom-banner

세마포어, 뮤텍스, 스핀 락에 대해 알기 전에 이것들이 언제 쓰이고 왜 쓰이는 지 먼저 알아야 한다.

멀티 코어 시스템에서는 여러 프로세스가 동시에 실행되어 시스템의 성능 향상을 목표로 한다. 이러한 환경에서 하나의 공유 자원을 한 프로세스가 사용중일 때, 다른 프로세스가 동시에 사용하려고 하면 여러 문제가 발생한다. 서로 같은 값을 변경하려고 하거나 읽는 도중에 값이 바뀌어 오류가 생길 수도 있다. 이러한 문제들을 동기화 문제라고 하며 이렇게 동시에 사용될 수 있는 자원을 임계 영역이라고 한다.
임계 영역에 대해 알아본 후에 세마포어, 뮤텍스, 스핀락에 대해 알아보자.

 

Critical Section (임계 영역)


임계 영역이란 프로세스 간의 공유 자원을 접근하는 데 있어서 문제가 발생하지 않도록 한 번에 하나의 프로세스만 이용하도록 다른 프로세스의 접근을 제한하는 영역을 말한다.

requirement

  1. 상호 배제 (Mutual Exclution)
    • 하나의 프로세스가 임계 영역에서 실행중이라면, 다른 프로세스는 해당 영역에 접근할 수 없어야 한다.
  1. 실행 (Process)
    • 임계 영역에서 실행중인 프로세스가 없을 때 들어가려는 프로세스가 여러 개라면 현재 대기중인 프로세스만이 진입 후보가 될 수 있고, 어느 것이 들어갈 것이지 결정해주어야 한다.
  1. 한정된 대기 (Bounded Waiting)
    • 한 프로세스가 임계 영역에 진입 요청 후 받아들여질 때 까지의 시간동안 다른 프로세스들이 임계 영역에 진입하는 횟수는 제한이 있어야 한다.
    • 다른 프로세스들의 기아(Starvation)을 막기 위함이다.

 

Spinlock (스핀락)


임계영역이 락이 걸려서 진입이 불가능할 때, 임계영역이 언락되어 진입이 가능해질 때까지 루프를 돌면서 재시도하여 스레드가 CPU를 점유하고 있는 상태이다.
CPU를 점유하여 무의미한 코드를 계속 수행하면서 임계영역이 언락되길 기다리는 것이기 때문에 스핀락은 Busy Waiting 상태이다.

스핀락은 운영체제의 스케줄링 지원을 받지 않기 때문에, 해당 스레드에 대한 문맥 교환(context switch)이 일어나지 않는다.

임계영역이 짧은 시간 안에 언락되어 진입이 가능한 상태이면 context switch 비용이 들지 않아 효율적일 수 있지만, 임계영역이 오랜 시간동안 언락되지 않으면 그 시간동안 계속 CPU를 점유하고 있어 다른 스레드가 사용하지 못하기 때문에 오버헤드도 존재한다.

스핀락은 상태가 오직 획득(Lock) / 해제(Unlock)만 존재하기에 한 번에 하나의 컴포넌트만 접근이 가능하며, 획득과 해제의 주체는 동일해야 한다.

스핀락은 context switch가 일어나지 않기 때문에 멀티 프로세서 시스템에서만 사용 가능하다.

 

Mutex (뮤텍스)


Mutex는 Mutual Exclusion의 약자로서 상호 배제라고도 한다. 뮤텍스는 상태가 오직 획득(Lock) / 해제(Unlock)만 존재한다는 점은 스핀락과 동일하다. 하지만 스핀락이 임계영역이 언락되어 권한을 획득하기까지 Busy Waiting 상태를 유지한다면, 뮤텍스는 Sleep 상태로 들어갔다 Wakeup 되면 다시 권한 획득을 시도한다.

뮤텍스의 경우에는 Locking 메커니즘으로 락을 걸은 스레드만이 임계영역을 나갈 때 락을 해제할 수 있습니다.

시스템 전반의 성능에 영향을 주고 싶지 않고 길게 처리해야하는 작업인 경우에 주로 사용된다. 주로 스레드 작업에서 많이 사용된다.

 

Semaphore (세마포어)


스핀락과 뮤택스와 달리 표현형이 정수형이다. 이 점을 살려 하나 이상의 컴포넌트가 공유자원에 접근할 수 있도록 허용할 수 있다.

컴포넌트가 특정 자원에 접근할 때 semWait이 먼저 호출되어 임계영역에 들어갈 수 있는지 먼저 확인한다. 임계영역에 접근이 가능하다면 semWait을 빠져나와 임계영역에 들어가고, 이후 semSignal이 호출되어 임계영역에서 빠져나옵니다.

  • semWait 연산
    세마포어의 값을 감소. 만약 값이 음수가 되면 semWait을 호출한 스레드는 블록되지만 음수가 아니면 작업을 수행한다.
  • semSignal 연산
    세마포어의 값을 증가. 만약 값이 양수가 아니라면 semWait 연산에 의해 블록된 스레드를 다시 wake시킨다.

세마포어는 Signaling 메커니즘으로 락을 걸지 않은 스레드도 signal을 통해 락을 해제할 수 있다.

위 그림과 같이 TASK A가 먼저 스케줄링되어 post_work()를 먼저 할 수 있는 상황이고 초기 세마포어의 값을 0으로 초기화 하여 post_work를 호출하지 못한다고 하자. 그러고 TASK B의 pre_work()가 끝난 후 세마포어의 값을 올려 TASK A의 post_work()를 호출할 수 있도록 할 수 있다.

세마포어의 값은 자원의 수를 의미하고, 세마포어는 사용할 수 있는 자원의 개수에 따라 두가지 유형이 있다.

Counting Semaphore(개수 세마포어)

  • 도메인이 0 이상인 임의의 정수값인 세마포어이다.
  • 여러개의 자원을 가질 수 있으며, 제한된 자원을 가지고 액세스 작업할 때 사용한다.

Binary Semaphore (이진 세마포어)

  • 0 또는 1 값만 가질 수 있는 세마포어이다.
  • 임계영역 문제를 해결하는 데에 사용하며, 자원이 하나이기 때문에 뮤텍스로도 사용할 수 있다.

참고
한재엽님 Github - 운영체제
https://yoongrammer.tistory.com/63
https://cocoon1787.tistory.com/541
https://ko.wikipedia.org/wiki/스핀락
https://selfish-developer.com/entry/스핀락-뮤텍스-세마포어

profile
컴퓨터 관련 여러 분야 공부중
post-custom-banner

0개의 댓글