백엔드 면접 용어 사전
운영체제race condition

경쟁 조건

공유 자원에 대한 접근 순서에 따라 결과가 달라지는 결함. 원자성이 깨질 때 발생한다.

여러 실행 흐름이 공유 자원에 접근하는 순서에 따라 결과가 달라지는 결함 (race condition). 순서가 "경주"처럼 매번 달라진다는 뜻이다.

왜 생기는가 — 원자성이 깨지기 때문

count++;

자바 코드로는 한 줄이지만 CPU에서는 세 단계다.

1. LOAD   count → 레지스터   (메모리에서 읽기)
2. ADD    레지스터 + 1
3. STORE  레지스터 → count   (메모리에 쓰기)

스레드 A와 B가 count = 5일 때 동시에 시작하면

A: LOAD 5          B: LOAD 5      ← 둘 다 5를 읽음
A: ADD  → 6        B: ADD  → 6
A: STORE 6         B: STORE 6     ← 결과 6. 7이어야 하는데 하나가 사라짐

이것을 갱신 손실(lost update) 이라 한다.

원자성 말고 또 하나 — 가시성

멀티코어에서는 각 코어가 자기 캐시에 값을 들고 있다. A가 쓴 값이 메인 메모리로 내려가기 전에는 B가 옛 값을 볼 수 있다.

boolean flag = false;   // A가 true로 바꿔도
while (!flag) { }       // B는 영원히 false를 볼 수 있다

자바의 volatile은 이 가시성을 보장한다(캐시를 거치지 않고 메인 메모리에서 읽고 쓴다). 다만 원자성은 보장하지 않는다volatile int count; count++ 는 여전히 안전하지 않다. 이 구분이 면접 단골이다.

해결 수단

수단보장비용
synchronized·Lock원자성 + 가시성대기·컨텍스트 스위칭
volatile가시성만매우 낮음
AtomicInteger (CAS)원자성 + 가시성경쟁 심하면 재시도 폭증
불변 객체애초에 변경이 없음없음 — 가장 좋은 해법
ThreadLocal공유를 안 함메모리, 누수 주의

재현이 어렵다는 점이 무섭다

타이밍에 의존하므로 개발 환경에서는 안 나고 운영에서만 터진다. 그래서 "테스트를 통과했으니 괜찮다"가 성립하지 않는다. 설계 단계에서 공유 상태를 줄이는 것이 최선의 방어다.

실무 연결

스프링의 싱글톤 빈에 인스턴스 변수를 두면 모든 요청이 그것을 공유한다. 이것이 가장 흔한 실전 경쟁 조건이다 — 상태는 지역 변수나 파라미터로 다뤄야 한다.

함께 보면 좋은 용어

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