Appearance
[OS] Race Condition
공유 자원에 여러 실행 흐름이 동시에 접근할 때, 실행 순서에 따라 결과가 달라지는 상태를 말한다.
동시 접근 시 자료의 일관성이 깨질 수 있다.
Race Condition이 발생하는 경우
인터럽트 컨텍스트와 일반 커널 컨텍스트가 같은 데이터를 건드릴 때
- 문제점: 일반 커널 코드가 공유 데이터를 수정하는 도중 인터럽트 핸들러가 같은 데이터를 건드릴 수 있다.
- 해결법: 아주 짧은 구간에서는 로컬 인터럽트를 막거나, 보통은
irqsave계열 스핀락처럼 인터럽트 안전한 락을 사용한다.
커널 코드가 선점(preemption)되거나 다른 커널 스레드와 경쟁할 때
- 문제점: 현대 커널은 커널 모드라고 해서 항상 "절대 문맥 교환되지 않는다"는 보장이 없다. 선점형 커널에서는 같은 공유 상태를 두 실행 흐름이 번갈아 만질 수 있다.
- 해결법: 뮤텍스, 스핀락, 원자 연산, refcount, seqlock 등 상황에 맞는 동기화 기법으로 보호한다.
멀티코어/멀티프로세서 환경에서 같은 공유 메모리를 접근할 때
- 문제점: 서로 다른 CPU가 동시에 같은 데이터를 읽고 쓰면 단일 CPU보다 더 쉽게 race condition이 발생한다.
- 해결법: 락뿐 아니라 메모리 순서(memory ordering) 까지 고려한 동기화가 필요하다.
사용자 공간의 멀티스레드 프로그램에서 공유 데이터를 접근할 때
- 문제점: 전역 변수, 힙 객체, 큐 등을 여러 스레드가 동시에 수정하면 잘못된 결과가 나온다.
- 해결법: 뮤텍스, 조건 변수, 세마포어, 원자 연산 같은 사용자 공간 동기화 도구를 사용한다.
핵심 정리
- race condition은 "여러 주체가 동시에 접근한다"는 사실 자체보다, 그 접근 순서에 따라 결과가 달라진다는 점이 핵심이다.
- 커널 모드라고 해서 자동으로 안전하지 않다.
- 단일 CPU에서도 인터럽트와 선점 때문에 race condition은 발생할 수 있다.
- 멀티코어에서는 락과 함께 메모리 가시성까지 고려해야 한다.