Semaphore

유석현(SeokHyun Yu)·2023년 6월 14일
0

운영체제

목록 보기
15/22
post-thumbnail

1. 개요

다양한 범주의 병행성 문제 해결을 위해서는 락과 조건 변수가 모두 필요하다.


2. 세마포어: 정의

세마포어정수 값을 갖는 객체로서 두 개의 루틴으로 조작할 수 있다.

이 두 개의 루틴은 sem_wait()sem_post()이다.

세마포어는 초기값에 의해 동작이 결정되기 때문에, 사용하기 전 제일 먼저 값을 초기화해야 한다.

우선 몇 가지 핵심적인 성질을 논의하겠다.

첫 번째, sem_wait() 함수는 즉시 리턴하거나 (세마포어의 값이 1 이상이면), 아니면 해당 세마포어 값이 1 이상이 될 때까지 호출자를 대기시킨다.

다수의 스레드들이 sem_wait()를 호출할 수 있기 때문에, 대기큐에는 다수의 스레드가 존재할 수 있다.

대기하는 법에는 회전(spin)과 재우기(sleep)의 두 가지가 있다는 것을 상기하자.

두 번째, sem_wait() 함수와 달리 sem_post() 함수는 대기하지 않는다.

세마포어 값을 증가시키고 대기 중인 스레드 중 하나를 깨운다.

세 번째로, 세마포어가 음수라면 그 값은 현재 대기 중인 스레드의 개수와 같다.


3. 이진 세마포어(락)

우리가 처음으로 세마포어를 적용할 곳은 이미 친숙한 락이다.

락은 두 개의 상태(사용 가능, 사용 중)만 존재하므로 이진 세마포어(binary semaphore)라고도 불린다.


4. 순서 보장을 위한 세마포어

세마포어는 병행 프로그램에서 일어나는 사건들의 순서(order)를 정하는 데에도 유용하다.

이전에 컨디션 변수를 사용했던 것과 유사하게 세마포어를 순서를 정하기 위한 기본 도구로 사용할 수 있다.


5. 생산자/소비자(유한 버퍼) 문제

다음 문제는 생산자/소비자 문제 또는 유한 버퍼라고 불리는 문제이다.

문제를 해결하는 첫 번째 시도에서 우리는 emptyfull이라는 두 개의 세마포어를 사용한다.

스레드는 empty를 사용하여 가용 버퍼 공간이 있는지, full를 사용하여 읽을 내용이 있는지 여부를 표시한다.

이는 공유변수 접근시 상호 배제를 고려하지 않았다.

최종적으로 문제를 해결하기 위해서는 락의 범위(scope)를 줄여야 한다.


6. Reader-Writer 락

다양한 자료구조를 접근할 때, 각 자료 구조의 특성과 접근 방식을 적절히 고려한 여러 종류의 락 기법이 필요하다.

다수의 스레드가 연결 리스트에 노드를 삽입하고 검색을 하는 상황을 가정해보자.

삽입 연산은 리스트를 변경한다.

검색은 리스트를 변경시키지 않고 단순히 읽기만 한다.

삽입 연산이 없다는 보장만 된다면 다수의 검색 작업을 동시에 수행할 수 있다.

이와 같은 경우를 위해 만들어진 락이 reader-writer 락이다.

자료 구조를 갱신하려면 배타적 접근권한을 갖는 락을 사용한다.

그냥 우리가 잘 아는 락이다.

하나의 쓰기 스레드만이 락을 획득할 수 있도록 하여, 임계 영역 진입 후에 자료 구조를 갱신한다.

읽기 락은 동시에 여러 스레드가 락을 보유할 수 있다.

읽기 락을 획득 시 읽기 스레드(reader)가 먼저 락을 획득하고 읽기 중인 스레드의 수를 표현하는 readers 변수를 증가시킨다.

profile
Backend Engineer

0개의 댓글