OS에서 Race Condition 발생 상황
(1) Kernel 수행 중 인터럽트 발생 시
: 인터럽트 처리 때문에 OS 내부의 공유 데이터에 접근하여 발생하는 경우
: 인터럽트를 disable해서 해결한다.
(2) Process가 시스템 콜을 하여 kernel mode로 수행 중인데 문맥 교환이 발생하는 경우
(3) Multiprocessor에서 공유 메모리 내의 kernel data
: 한번에 하나의 CPU만 커널에 들어가게 만들어 OS를 공유하지 않게 만든다는 취지.
: 오버헤드가 발생하므로, OS 전체가 아닌 공유 데이터 각각을 lock / unlock해서 구현한다.
do {
while(turn != 0);
critical section
turn = 1;
remainder section
} while (1);
do {
flag[i] = true;
while(flag[i]);
critical section
flag[i] = false;
remainder section
} while (1);
do {
flag[i] = true;
turn = j;
while(flag[i] && turn == j);
critical section
flag[i] = false;
remainder section
} while (1);
Synchronization Hardware
동기화를 하드웨어단에서 지원해서 문제 해결하기
: 하드웨어적으로 CPU 접근을 쪼개지 않고 한번에 하도록 만들면 임계영역 접근 문제를 해결할 수 있다.
지금까지의 방식들을 추상화시킨 것. 일종의 추상 자료형
세마포어를 이용, race condition 문제를 추상 자료형으로 해결할 수 있다.
(1) Busy-wait
: 변수값을 주고 처리
: busy waiting 문제 발생
(2) Block / Wakeup Implementation
: 세마포어를 일종의 구조체로 정의
: 큐를 이용, 실행 중 오래 걸리는 작업에 걸리면 잠들게 두고(대기), 나머지 작업은 세마포어를 쓸 수 있게 만든다.
: P연산 - 세마포어 자원이 음수라면 여분이 없는 상태 = 리스트에 프로세스를 동결시킨다.
: V연산 - 세마포어 자원이 반납되어 양수가 되면 여분 생김 = block된 프로세스를 wakeup 시킨다.
세마포어 구현법 비교
(1) 임계영역 길이가 긴 경우, Block/Wakeup이 적당
(2) 임계영역 길이가 매우 짧은 경우(경쟁이 치열하지 않은 경우), Block/Wakeup 오버헤드가 busy-wait 오버헤드보다 커질 수 있다! (굳이 재우고 깨울 필요 없다)
(3) 그래도 일반적으로 Block/Wakeup이 더 좋다
Counting Semaphore
: 도메인이 0 이상인 임의의 정수값.
: 리소스 카운팅에 주로 사용
Binary Semaphore (=mutex)
: 0 또는 1만 가질 수 있는 세마포어
: 주로 상호 배제 - lock/unlock에 사용