
레이스 컨디션은 dead lock(교착 상태), starvation(기아)과 함께 병행 처리의 문제 중 하나로, 공유 리소스에 대한 상호배타 미보장에 의해 발생한다.
(dead lock은 유효한 진행 미보장과 starvation은 유한대기 미보장에 의해서 발생한다.)
레이스 컨디션(Race Condition)은 둘 이상의 프로세스나 스레드가 동시에 동일한 공유 자원에 접근할 때 발생하는 문제다. 특히 이들 중 하나라도 쓰기(write) 작업을 수행하는 경우, 실행 순서에 따라 프로그램의 결과가 달라질 수 있다.
이런 상황은 시스템의 예측 가능성을 무너뜨리고, 치명적인 버그나 데이터 손상을 야기할 수 있다. 예를 들어 두 스레드가 동시에 같은 은행 계좌에서 출금 요청을 처리할 경우, 잔고가 음수가 되는 등의 비정상적인 결과가 발생할 수 있다. 이러한 문제는 재현이 어렵고 디버깅 또한 까다롭기 때문에, 안정적인 시스템을 설계하려면 반드시 해결해야 할 중요한 동시성 이슈다.
동일한 시점에 오직 하나의 스레드만이 임계 영역에 진입하도록 보장하는 원칙이다. (임계 영역(Critical Section)이란 코드에서 특정 자원에 접근하는 부분이다.)
즉, 특정 공유 자원에는 하나의 스레드씩만 접근(읽기든, 쓰기든)하도록 하고, 이를 통해 레이스 컨디션을 방지한다.
이 상호배타를 보장하는 동기화 도구로는 뮤텍스(Mutex)가 있다.
임계 영역, 즉 공유 자원에 한 번에 하나의 스레드만 접근할 수 있도록 제어하는 잠금 장치이다.
뮤텍스의 두 가지 상태
즉, 뮤텍스의 소유권을 특정 스레드가 갖고, 그 시간 동안 임계 영역을 독점한다. Unlock은 뮤텍스를 소유한 스레드만이 직접할 수 있다.
mutex_lock();
for (int i = 0; i < 10000; i++) {
count++;
}
mutex_unlock();
뮤텍스를 사용해도, 만약 뮤텍스를 소유한 스레드가 unlock하지 않고, 죽는다면, dead lock 상태에 빠지게 된다.
또한 뮤텍스를 쟁취하는 과정에서 다시 한번 레이스 컨디션이 발생할 수 있다. 이 경우는 하드웨어 수준의 atomic instruction을 이용해 처리해야 한다.