Race Condition

동기화 불변식

경쟁 조건은 두 실행 흐름이 같은 상태를 읽고 쓰는 순서가 바뀌면서 결과가 달라질 때 생긴다. 보호할 대상은 변수 하나가 아니라 상태 사이의 약속이다.

01

공유 상태 표시

전역 변수, heap 객체, 파일 offset, queue처럼 여러 스레드가 접근하는 값을 먼저 찾는다.

02

불변식을 적는다

size와 buffer 내용, head와 tail, balance와 ledger처럼 같이 맞아야 하는 조건을 문장으로 만든다.

03

interleaving을 검사한다

읽기와 쓰기 사이에 다른 스레드가 끼어들 때 lost update나 깨진 상태가 생기는지 본다.

Race
순서 의존 결과 실행 순서가 달라지면 결과도 달라지는 버그다.
재현이 어렵다.
Atomicity
쪼개지지 않는 동작 읽기-수정-쓰기 전체가 하나처럼 보여야 할 때가 있다.
counter 증가도 단일 명령이 아닐 수 있다.
Visibility
보이는 시점 한 CPU의 쓰기가 다른 CPU에 언제 보이는지 메모리 모델과 cache가 관여한다.
lock은 가시성도 제공한다.
Invariant
함께 맞는 조건 여러 필드가 동시에 의미를 이룰 때 부분 업데이트가 위험하다.
lock 범위는 이 조건을 기준으로 잡는다.

공유 여부 · 원자성 · 범위 점검

공유 여부 두 실행 흐름이 같은 메모리나 외부 자원에 접근하는가.
원자성 읽기와 쓰기 사이에 끼어들면 깨지는 연산이 있는가.
범위 lock이 변수 하나가 아니라 불변식 전체를 감싸는가.

위험한 증가

tmp = counter;
tmp = tmp + 1;
counter = tmp;
// 세 단계 사이에 다른 스레드가 끼어들 수 있다.