세마포어


1 개요

세마포어는 에츠허르 다익스트라 가 제안한 교착 상태에 대한 해법으로 두개의 Atomic한 함수로 제어되는 정수 변수로 멀티프로그래밍 환경에서 공유자원에 대한 접근 제어를 하는 방식으로 1개의 공유되는 자원에 제한된 개수의 프로세스, 또는 스레드만 접근할 수 있도록 한다.[1] 다만, 해당 방법은 모든 교착 상태에 대한 해답을 제시해 줄 수 없으나 교착 상태 해법에 대한 고전적인 해법으로 아직도 대다수의 운영체제 과목 및 시스템 프로그래밍 과목에서 언급되는 개념이다. 이 방법으로 해결되는 대표적인 문제가 식사 하는 철학자 문제 이다.

2 왜 필요한가

예를 들어, 아래의 변수가 있다고 하자.
int a = 0;
이러한 상황에 해당 값은 전역변수로 설정되어있고, 이 프로그램은 여러개의 쓰레드가 a의 값을 증가시키는 프로그램이라고 할 때 이러한 증상이 발생한다.
Process A -> fetch a(0)
Process B -> fetch a(0)
Process A -> increase a(1)
Process A -> Store a back(1)
Process B -> increase a(1)
Process B -> Store a back(1)
여기서, 외부에서 보게되면 변수 a에 대해서 1씩 증가하는 과정이 2번 일어났다. 그럼으로 B프로세스가 종료되었을 때는 a는 2가 되어야 하나 여기서는 1이 되어버렸다. 즉, A가 결과를 주기 전에 B가 수행되면서 엉뚱한 값을 시작값으로 가져와서 결과가 잘못 나와 버렸다. 이를 방지하기 위해서 세마포어를 이용하여 a 변수에 Process A가 접근 하고 있을 때 Process B를 정지 시키고 Process A가 종료 되었을 때 B가 시작되도록 다시 시작하게 하면 해결된다.

3 작동 원리

세마포어의 작동 원리는 상호 배제 알고리즘(Mutual Exclusion)에 기반한다. 세마포어는 원자적으로 제어되는 정수 변수로, 일반적으로 세마포어의 값이 0이면 자원에 접근할 수 없도록 블럭을 하고 0보다 크면 접근함과 동시에 세마포어의 값을 1 감소시킨다. 반대로 종료하고 나갈 때에는 세마포어의 값을 1 증가시켜 다른 프로세스가 접근할 수 있도록 한다. 여기서 접근되는 자원은 임계 구역으로 이 설정에 따라서 프로그램의 퍼포먼스가 극단적으로 하락할 수 있어 사용에 세심한 주의가 필요하다.[2]

4 방법

4.1 Busy Waiting

최초에 제시된 방안으로 바쁜 대기[3]를 하게된다. 바쁜대기란 아무것도 하지 않는 빈 반복문을 게속해서 반복하다가 임계 구역에 진입할 수 있을 때 진입하는 방식으로, 빈 반복문을 반복하기때문에 계속적으로 컨텍스트 교환이 발생하며 이로 인하여 처리 효율이 떨어지는 단점이 있다. 또한, 어떠한 프로세스가 먼저 임계 구역에 진입을 할 수 있을지에 대한 처리를 할 수 없다는 단점 또한 존재한다.
  1. 세마포어의 카운트는 1 이상이며 카운트를 조절하여 진입 가능한 프로세스/스레드 수를 조절할 수 있다. 세마포터 카운트가 항상 1인 것은 아니다.
  2. 디자인 패턴의 싱글톤 패턴을 생각해보면 이해가 용이하다. 여러개의 스레드가 1개의 싱글톤 패턴으로 만들어진 오브젝트를 이용하려 할 때가 제어를 하는것이 바로 세마포어가 하는것과 동일한 역할이다.
  3. Busy waiting이라고도 부른다