---
title: "세마포어는 자원의 개수와 작업 완료를 어떻게 표현할까"
author: "Lee"
published_at: "2026-10-08T15:49:02.363Z"
updated_at: "2026-09-30T09:39:02.498Z"
tags: ["컴퓨터공학","운영체제"]
canonical_url: "https://ariser.io/@writer_a1cd615ab19e/%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4%EB%8A%94-%EC%9E%90%EC%9B%90%EC%9D%98-%EA%B0%9C%EC%88%98%EC%99%80-%EC%9E%91%EC%97%85-%EC%99%84%EB%A3%8C%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%91%9C%ED%98%84%ED%95%A0%EA%B9%8C"
ai_assisted: false
---

# 세마포어는 자원의 개수와 작업 완료를 어떻게 표현할까

[원문](https://ariser.io/@writer_a1cd615ab19e/%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4%EB%8A%94-%EC%9E%90%EC%9B%90%EC%9D%98-%EA%B0%9C%EC%88%98%EC%99%80-%EC%9E%91%EC%97%85-%EC%99%84%EB%A3%8C%EB%A5%BC-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%91%9C%ED%98%84%ED%95%A0%EA%B9%8C)

세마포어는 정수 카운터와 원자적인 획득·반환 동작으로 동시 실행을 조절하는 도구다. 허용량이 남으면 작업이 하나를 사용하고 진행하며, 없으면 기다린다. 허용량을 돌려주면 다른 작업이 진행할 수 있다. 하나씩만 들어가게 하는 상호 배제부터 여러 자원의 동시 사용, 작업 사이의 완료 알림까지 같은 기본 장치를 다른 방식으로 사용할 수 있다.

![연결 세 개를 사용 중인 요청 세 개와 세마포어 허용량을 기다리는 네 번째 요청](/api/v1/media/786a18ee-5237-4637-a525-8e8841587ab0)

*세마포어 카운터가 세는 대상과 획득·반환 규칙을 함께 정해야 한다.*

## 카운터에 붙인 의미가 중요하다

데이터베이스 연결 세 개를 가진 풀을 생각해 보자. 세마포어의 초기 허용량을 3으로 둔다. 요청은 연결을 사용하기 전에 `wait`로 허용량을 얻고, 사용이 끝나면 `post`로 돌려준다. 세 요청이 모두 사용하는 동안 네 번째 요청은 기다린다. 단, 세마포어는 연결 객체 자체를 고르는 자료구조까지 제공하지 않는다. 풀 안의 객체 목록도 올바르게 관리해야 한다.

카운터 감소와 가능 여부 확인은 하나의 원자적인 동작이어야 한다. 두 작업이 허용량 1을 동시에 확인하고 각각 사용하면 제한을 넘기기 때문이다. POSIX의 [sem_wait 설명](https://man7.org/linux/man-pages/man3/sem_wait.3.html)은 값이 양수일 때 감소시키며, 즉시 감소할 수 없으면 대기하는 동작을 규정한다. 교육용 표현에서 음수로 대기자 수를 나타내기도 하지만 모든 API가 이를 외부에 그대로 보여 주는 것은 아니다.

## 허용량을 반환하는 경로까지 설계한다

획득한 작업이 오류나 예외로 끝나더라도 허용량을 돌려주지 않으면 다른 작업이 계속 기다릴 수 있다. 반대로 획득하지 않았는데 반환하거나 한 번 획득하고 두 번 반환하면 동시 사용 한도가 무너진다. 자원 수 제한은 카운터 초기화만으로 끝나지 않는다. 획득 성공 여부, 객체 수명, 모든 종료 경로의 반환을 연결해야 한다.

초기값을 0으로 두면 다른 의미를 만들 수 있다. A가 작업을 끝낸 뒤 `post`하고, B가 `wait`한 뒤 이어서 진행하면 완료 알림이 된다. A가 먼저 끝나도 허용량이 남아 B가 나중에 받을 수 있다. 알림 자체를 기억하지 않는 조건 변수와 비교할 때 세마포어의 카운터가 가진 의미가 드러난다.

## 뮤텍스와 닮았지만 같지는 않다

초기값 1인 이진 세마포어는 한 작업만 통과하게 하는 데 쓸 수 있다. 그러나 일반적인 뮤텍스는 소유권이 있어 획득한 실행 흐름이 해제한다. 세마포어는 생산자가 허용량을 추가하고 소비자가 가져가는 것처럼 다른 실행 흐름이 두 동작을 맡을 수 있다. 따라서 둘을 무조건 교환 가능한 잠금으로 생각하면 규약을 놓친다.

대기 순서의 공정성은 구현과 API에 따라 다르다. 먼저 기다렸다고 항상 먼저 깨어난다고 가정하면 안 된다. 세마포어를 여러 개 반대 순서로 획득하면 교착 상태도 생길 수 있다. 허용량이 충분해도 공유 자료의 복합 갱신까지 자동으로 보호되는 것은 아니므로 별도의 임계 구역이 필요한지 판단해야 한다.

세마포어는 동시 요청 수, 작업 파이프라인의 슬롯, 생산된 항목 수를 표현할 때 유용하다. 올바른 사용의 출발점은 이 카운터가 무엇을 세는지 한 문장으로 말하는 것이다. 사용 가능한 연결인지, 비어 있는 버퍼 칸인지, 완료된 작업인지가 명확하면 초기값과 증감 위치, 실패 시 복구 규칙도 자연스럽게 정해진다.

### 참고 자료

- [Linux man-pages — sem_wait(3)](https://man7.org/linux/man-pages/man3/sem_wait.3.html)
