운영체제 따라잡기

동시성 문제 사례

meellon 2026. 6. 28. 05:00

학습 목표

Producer-Consumer 문제에서 빈 슬롯·채운 슬롯 세마포어와 뮤텍스 역할을 설명할 수 있다.

Readers-Writers 문제에서 읽기 공유·쓰기 배타 요구를 설명할 수 있다.

고전 패턴이 실무 큐·캐시·connection pool 과 어떻게 대응되는지 설명할 수 있다.

패턴별로 어떤 동기화 primitive를 쓰는지 선택할 수 있다.

문제 상황

  • 로그 수집기가 버퍼가 가득인데도 계속 쓰거나, 소비자가 빈 큐에서 pop한다
    • 생산·소비 속도 차이를 경계 있는 버퍼로 흡수해야 한다
  • 설정 파일은 여러 goroutine이 동시에 읽어도 되는데, 한 번에 하나만 저장해야 한다
    • 읽기·쓰기에 다른 잠금 규칙이 필요하다
  • 뮤텍스·세마포어 문법은 알지만 어디에 무엇을 걸지 모른다
    • 고전 사례가 템플릿이 된다
  • BlockingQueue·sync.RWMutex가 OS 교재의 어떤 그림과 같은지 연결이 안 된다

동기화 도구와 데드락을 봤다. 이번 편은 도구를 어디에 쓰는지 — 대표 패턴으로 정리한다.

1. Producer-Consumer (생산자-소비자)

생산자는 아이템을 만들어 버퍼에 넣고, 소비자는 꺼내 처리한다. 버퍼 크기는 유한(bounded buffer).

동기화 역할
mutex 버퍼 구조(in/out 인덱스) 배타 접근
empty (세마포어) 빈 슬롯 개수 — 생산 전 wait
full (세마포어) 채운 슬롯 개수 — 소비 전 wait

생산자 의사코드:

while (true) {
    produce item
    wait(empty)
    wait(mutex)
       add item to buffer
    signal(mutex)
    signal(full)
}

소비자는 wait(full)wait(mutex) → 제거 → signal(mutex)signal(empty) 순서.

  • 실무: BlockingQueue, Kafka consumer lag, channel(goroutine), ArrayBlockingQueue
  • wait 순서: 뮤텍스 전에 세마포어를 기다리면 데드락 위험 줄임 (빈 슬롯 없으면 mutex 안 잡음)

2. Readers-Writers (독자-저자)

Reader는 동시에 여러 개 가능, Writer배타적 — 쓰는 동안 읽기·쓰기 모두 불가.

첫 번째 Readers-Writers (Reader 우선)

변수 역할
read_count 현재 읽는 reader 수
mutex read_count 갱신 보호
rw_mutex writer 진입 배제

Reader: read_count++가 1이면 rw_mutex 획득 → 읽기 → read_count--가 0이면 rw_mutex 해제.

Writer: rw_mutex 획득 → 쓰기 → 해제.

  • 문제: reader가 계속 오면 writer starvation

Writer 우선·공정 버전

  • Writer 우선: 대기 writer가 있으면 새 reader 차단
  • 공정: 큐(FIFO)로 reader·writer 순서 보장 — std::shared_mutex, Java ReadWriteLock 구현에 가깝다

실무 대응

패턴
다중 reader 설정 캐시, feature flag 조회
단일 writer 설정 저장, 스냅샷 갱신
API DB 읽기 복제본 + 쓰기 마스터 (물리적 분리)

3. Dining Philosophers (식사하는 철학자) — 개요

5명이 원탁, 젓가락 5개 — 식사하려면 양쪽 젓가락 필요.

  • 둘 다 잡는 순서가 순환이면 데드락 (앞서 본 순환 대기)
  • 해법: 젓가락 전역 순서, 홀수·짝수 다른 순서, 세마포어로 동시 식사자 수 제한

교과서에서 데드락·동기화 복합 예제로 자주 나온다. 실무에서는 두 리소스를 동시에 잡는 패턴(DB 두 테이블 락, 분산 락 2개)에 대응한다.

4. 패턴 선택 요약

패턴 핵심 제약 주요 primitive
Producer-Consumer 버퍼 크기·생산/소비 속도 2 세마포어 + mutex
Readers-Writers 읽기 공유, 쓰기 배타 rw_mutex, read_count, (공정 큐)
Bounded parallel work 동시 실행 수 N counting semaphore, worker pool
Single-flight 같은 key 한 번만 계산 mutex + map, `sync.Singleflight`

5. 정리

  • Producer-Consumer: empty/full 세마포어로 슬롯 수, mutex로 버퍼 무결성
  • Readers-Writers: reader 병렬·writer 배타, 우선순위에 따라 starvation 트레이드오프
  • 고전 패턴은 큐·캐시·RWLock의 설계 언어
  • 다음: 물리 메모리를 프로세스에 나눠 주는 방식 — 메모리 관리

다음에 다룰 것

  • 메모리 관리 기초
  • 연속 할당, 단편화, 페이징 개요

해당 내용은 Operating System Concepts, 10/E (Avraham Silberschatz, Peter Baer Galvin, Greg Gagne) 의 내용을 기반으로 합니다.

'운영체제 따라잡기' 카테고리의 다른 글

페이징  (0) 2026.06.30
메모리 관리 기초  (0) 2026.06.29
데드락 해결  (0) 2026.06.27
데드락 기초  (0) 2026.06.26
동기화 도구  (0) 2026.06.25