1. 프로세스 충돌
컴퓨터 시스템 내부에서는 다양한 이벤트(쓰레드)들이 컴퓨터 자원을 사이에 두고 동시다발적으로 발생한다. 이들이 실행되며 충돌하는 경우가 빈번히 발생한다.
Race condition
두 개 이상의 프로세스가 거의 동시에 접근하여 처리된 순서를 가릴 수 없는 상황을 말한다.
Mutual exclusion
두 개 이상의 프로세스가 같은 메모리에 접근하는 상황에서 (공유 자원을 할당받아 사용할 떄) 한 번에 한 프로세스씩 액세스하도록 하는 성질. (상호배제)
Race condition을 방지하기 위해선 Mutial Exclusion 성질이 만족되도록 프로그래밍되어야 한다.
Critical section
공유 영역에서 값을 변경시키는 행위
Starvation
요청한 자원이 오랜 기간 동안 배정되지 않아 기다려야 하는 비정상적인 상황을 말한다. 수치적인 기준이 존재하는 것은 아니고, 보통 상대적으로 판단한다.
결론적으로 공유 자원을 할당받는 과정에서 Race condition이 발생하는 것을 방지하여야 하는데, 운영체제보단 컴퓨터 사용자가 구현한 응용 프로그램 내에서 발생할 가능성이 높다. 공유 자원의 예시로는 IPC에서 학습한 Process간의 데이터 교환 시 사용하는 Shared memory 영역 내부의 변수들을 말할 수 있다. 프로세스 간의 충돌이 발생하기도 하고, 한 프로세스 내부에서 여러 개의 쓰레드가 동작할 때 발생하기도 한다.
Race condition을 방지하는 방법
1. Critical section to atomic operations. Critical section을 마치 하나의 instruction인 것처럼 실행하여 도중에 중단되지 않도록 구성한다. 물론 도중에 Interrupt는 발생하지만, CPU가 이에 대한 응답을 하지 않게 된다.
그러나 위 방법에는 문제가 한 가지 존재하는데, 원자화된 영역 내부에 수많은 instruction이 존재한다면 Interrupt를 막고 나서 다시 처리하기 까지 걸리는 텀이 굉장히 길어질 수 있다.
2. Make a fense around a critical section. 한 번에 하나의 프로세스만 접근 가능한 울타리를 Critcal section 외부에 두른다. 이는 Mutual exclusion을 만족한다.
2. Critical-Section Problem
세 가지 조건
n개의 프로세스들이 공유 데이터를 서로 경쟁적으로 접근하여 값을 변경하고 참조하려 하는 상황. 이러한 문제를 해결하기 위해 세 가지 성질을 만족하여야 한다.
첫 번째로 앞쪽에서 설명한 Mutual exclusion이다. 하나의 프로세스만 자원에 접근가능하며 그 동안에는 다른 프로세스가 접근할 수 없어야 한다.
두 번째로는 Progress 성질인데, 다른 프로세스들이 공유 자원에 접근하지 않을 경우 내가 이를 실행할 수 있어야 함을 뜻한다. 당연한 말처럼 들릴 수도 있겠지만, 울타리를 어떻게 구현하느냐에 따라 이 성질을 만족하지 못할 수도 있다.
세 번째로 Bounded waiting이다. 다른 프로세스가 공유 자원에 접근해 있는 상태인 경우 대기를 하게 되는데, 이 대기 시간에 제한을 두는 것이다. CPU를 할당받는 프로세스만이 Instruction을 실행하여 공유자원에 접근할 수 있는 상태가 되는데, 복수의 프로세스 간 스케쥴링 결과 하나의 프로세스가 계속 접근하지 못하는 상황이 발생할 수 있다. 이론적으로 무한히 대기할 수 있게 되는데 이를 원천적으로 막아주는 성질이다.
구현
Peterson's Algorithm, Bakery Algorithm 등 코드를 통해 Critical section problem을 구현한 사례가 있지만, 시간이 지나며 사람들은 소프트웨어적으로 이를 구현하는 것이 바람직하지 않다는 것을 경험적으로 깨닫게 된다.