백엔드 면접 용어 사전
운영체제starvation · 기아

기아 상태

우선순위에 밀려 특정 주체가 자원을 계속 얻지 못하는 상태. 에이징으로 완화한다.

어떤 작업이 자원을 계속 얻지 못해 진행하지 못하는 상태(starvation). 데드락과 달리 시스템 전체는 잘 돌아가는데 특정 작업만 소외된다.

데드락과의 차이

데드락기아
전체 진행완전 정지다른 작업은 잘 됨
원인순환 대기스케줄링 불공정
해결 시사이클을 끊어야기다리면 풀릴 수도 있음
발견명확어렵다 — 평균 지표는 정상, p99만 나쁨

어떻게 생기나

① 우선순위 기반 스케줄링

  • 높은 우선순위 작업이 계속 들어옴
  • 낮은 우선순위 작업은 영원히 차례가 오지 않는다

② 불공정 락

new ReentrantLock();       // 기본 = 비공정

비공정 락은 막 도착한 스레드가 대기열을 건너뛰고 획득할 수 있다. 운 나쁜 스레드는 계속 밀린다.

왜 굳이 비공정이 기본인가 — 공정 락은 대기열 순서를 지키려고 매번 컨텍스트 스위칭을 하므로 처리량이 크게 떨어진다. 막 깨어난 스레드에게 바로 주면 스위칭 없이 진행되어 훨씬 빠르다. 처리량과 공정성의 트레이드오프다.

③ 읽기-쓰기 락 읽기가 끊임없이 들어오면 쓰기가 영원히 못 들어간다(writer starvation). 그래서 대부분의 구현이 쓰기 대기 중에는 새 읽기를 막는다.

해결 — 에이징(aging)

기다린 시간에 비례해 우선순위를 올린다.

  • 대기 시간이 길어질수록 우선순위 +1
  • 아무리 낮은 작업도 언젠가는 가장 높아진다 → 반드시 처리된다

리눅스 CFS(Completely Fair Scheduler)는 다른 방식으로 같은 목표를 이룬다 — 가상 실행 시간(vruntime)이 가장 적은 프로세스를 다음에 실행한다. 못 뛴 프로세스는 vruntime이 안 늘어 결국 차례가 온다.

실무에서 만나는 형태

① 커넥션 풀 고갈

  • 느린 쿼리가 커넥션을 오래 쥠 → 빠른 요청들도 커넥션을 못 받아 대기
  • 특정 API만 타임아웃 폭증

② 스레드 풀에서 한 종류의 작업이 독점

  • 느린 외부 API 호출이 스레드 풀을 다 차지
  • 빠른 내부 처리 요청까지 굶는다
  • 대응: 작업 종류별로 풀을 분리 (bulkhead 패턴)

③ 메시지 큐의 특정 파티션 키가 편중되면 그 파티션의 컨슈머만 밀려 해당 사용자만 지연된다.

라이브락 — 헷갈리는 개념

기아와 비슷하지만 다르다. 둘 다 계속 움직이는데 진전이 없는 상태다.

복도에서 마주친 두 사람이 서로 비켜 주려다 계속 같은 방향으로 움직이는 상황

CAS 재시도가 서로를 계속 실패시키거나, 데드락 회피 로직이 "둘 다 놓고 재시도"를 동시에 반복할 때 생긴다. 무작위 지연(jitter) 을 넣어 대칭을 깨는 것이 해법이다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 운영체제 — 프로세스/스레드·동기화·가상메모리