728x90
24. 세마포어
24.1 세마포어 : 정의
- 세마포어는 정수 값을 갖는 객체로서 두 개의 루틴으로 조작할 수 있다. POSIX 표준에서 이 두 개의 루틴은 sem_wait()와 sem_post()이다. 세마는 초기 값에 의해 동작이 결정되기 때문에, 사용하기 전 제일 먼저 값을 초기화 해야한다.
- 같은 프로세스 내의 쓰레드 간에 세마포어를 공유한다. 두 루틴들은 동시에 다수 쓰레드들에 의해 호출될 수 있다. 임계영역이 적절히 보호되어야 한다. 임계영역 보호를 위해 사용할 함수내에서 임계영역 보호문제가 존재한다.
- sem_wait() 함수는 세마포어 값이 1 이상이면 즉시 리턴하거나, 해당 세마포어 값이 1 이상이 될 때까지 호출자를 대기시킨다. 다수의 쓰레드들이 sem_wait()을 호출 할 수 있기 때문에, 대기 큐에는 다수의 쓰레드가 존재할 수 있다. 대기하는 법에는 회전과 재우기 두 가지가 있다는 것을 상기하자
- sema_post()함수는 대기하지 않는다. 세마포어 값을 증가시키고 대기 중인 쓰레드 중 하나를 깨운다.
- 세마포어가 음수라면 그 값은 현재 대기중인 쓰레드의 개수와 같다. 일반적으로 사용자는 이 값을 알 수 없다.
24.2 이진 세마포어(락)
- 락은 두 개의 상태(사용 가능, 사용 중)만 존재하므로 이진 세마포어 라고도 불린다.
24.3 순서보장을 위한 세마포어
- 세마포어는 병행 프로그램에서 일어나는 사건들의 순서를 정하는 데에도 유용하다. 예를 들어, 리스트에서 객체를 삭제하기 위해 리스트에 객체가 추가되기를 대기하는 쓰레드가 있을 수 있다. 이러한 사용 패턴을 보면 하나의 쓰레드가 사건의 발생을 기다리고, 또 다른 쓰레드는 해당 사건을 발생시킨 후, 시그널을 보내어 기다리는 쓰레드를 깨운다.
24.4 생산자/소비자(유한 버퍼) 문제
- empty와 full이라는 두 개의 세마포어를 사용한다. 쓰레드는 empty를 사용하여 가용 버퍼 공간이 있는지, full을 사용하여 읽은 내용이 있는지 여부를 표시한다.
- 생산자와 소비자 쓰레드가 각 하나씩 있고 CPU도 하나인 상황에 대해 살펴보자. 소비자 쓰레드가 먼저 실행되었다 가정하자. 소비자 쓰레드가 변수 값은 0으로 초기화 되었기 때문에 해당 명령으로 인해 full의 값은 -1로 감소되고, 소비자 쓰레드는 대기 모드가 된다. 누군가가 full값을 증가시키기를 기다려야 한다.
24.5 Reader - Writer 락
- 다수의 쓰레드가 연결 리스트에 노드를 삽입하고 검색을 하는 상황을 가정해보자. 삽입 연산은 리스트를 변경한다. 검색은 리스트를 변경하지 않고 단순히 읽기만 한다. 삽입 연산이 없다는 보장만 된다면 다수의 검색 작업을 동시에 수행할 수 있다. 이와 같은 경우를 위해 만들어진 락이 Reader - Writer락이다.
- 자료구조를 갱신하려면 배타적 접근 권한을 갖는 락을 사용한다. 내부적으로는 write lock 세마포어를 사용하여 하나의 쓰기 쓰레드만이 락을 획득 할 수 있도록 하여, 임계영역 진입 후에 자료 구조를 갱신한다.
- 읽기 락(reader lock)은 동시에 여러 쓰레드가 락을 보유 할 수 있다. 읽기 락을 획득시 읽기 쓰레드가 먼저 락을 획득하고 읽기 중인 쓰레드 수를 표현하는 reader의 값을 증가시킨다. 첫 번째 읽기 쓰레드가 읽기 락을 획득할 때 중요한 과정이 있다. 읽기 락 획득시 write lock 세마포어에 대해 sem_wait()을 호출하여 쓰기 락을 함께 획득한다. 획득한 쓰기 락은 읽기 락을 해제할 때, sem_post()로 다시 해제한다.
- 이 과정을 통해서 읽기 락을 획득하고 난 후, 다른 읽기 쓰레드들이 읽기 락을 획득할 수 있도록 한다. 다만, 쓰기 락을 획득하려는 쓰기 쓰레드들은 모든 읽기 쓰레드가 끝날 때까지 대기해야 한다.
- 이 방식은 공정성에 문제가 있다. 상대적으로 쓰기 쓰레드가 불리하다. 쓰기 쓰레드에게 기아 현상이 발생하기 쉽다.
24.6 쓰레드 제어
- 과도하게 많은 쓰레드가 동시에 수행되면 시스템 효율이 매우 나빠진다. 이런경우 프로그래머는 과도하게 많은에 대한 임계값을 정하고, 세마포어를 사용하여 문제가 되는 코드를 동시에 실행하는 쓰레드 개수를 제한한다. 우리는 이 접근법을 제어(throttling)라고 부르며 수락제어의 한 형태로 간주한다.
728x90
'책 > 운영체제' 카테고리의 다른 글
운영체제 26. 이벤트 기반의 병행성(event-based concurrency) (1) | 2024.03.24 |
---|---|
운영체제 25. 병행성 관련 버그 (0) | 2024.03.24 |
운영체제 22. 락 기반의 병행 자료 구조 (0) | 2024.03.19 |
운영체제 21. 락 (0) | 2024.03.18 |
운영체제 20. 병행성 : 개요 (0) | 2024.03.17 |