데이터 접근방식
왜 프로세스 동기화가 필요한가요 ?
결국, 공유하는 하나의 자원에 대해서, 여러 프로세스가 동시에 접근할 때 시간적인 차이로 생길 수 있는 데이터의 불일치문제가 존재할 수 있음
이러한 문제를 해결하고자 하는 것이 프로세스 동기화(Process Synchroniztion)이다.
여러 프로세스들이 동시에 공유데이터에 접근하는 상황
데이터의 최종연산 결과가, 마지막에 그 데이터 연산을 한 프로세스에 의해 달라지는 현상
일반적으로, 프로세스는 자기 주소영역에 데이터만 접근하므로, 동기화 문제가 발생하지 X
But, 본인이 수행할 수 없는 명령에 경우, OS에게 System call을 통해, 커널의 코드가 그 프로세스를 대신해서 명령을 수행함
언제 OS에서 경쟁조건을 발생시키는가요 ?
1. Kernel 수행 중 인터럽트 발생 시 (CPU 1개)
문제점
해결법
2. Process가 System call을 하며, Kernel Mode로 수행 중 Context Switch가 일어나는 경우
이상적인 방식
문제 상황
(1) 프로세스 A가 실행 중이다가 system call
(2) 커널 모드에서 count++ 수행하다가, 할당시간 만료로 CPU를 뺏김
(3) 프로세스 B가 커널 모드에서 count++ 수행 중, 시간 만료로 CPU 뺏김
(4) 프로세스 A가 CPU를 되돌려 받아, 아까 작업하던 count++ 진행
문제점
결과적으로 프로세스B의 count++는 반영되지 않음!
해결법
3. Multiprocessor에서 Shared Memory 내에 Kernel data에 접근하는 경우
문제점
해결법
방법1. 한 번에 하나의 CPU만이 커널에 들어갈 수 있도록 하고, 하나의 커널을 lock으로 막고, 커널을 빠져나올 때 unlock. (커널 전체를 lock하기 때문에 비효율적)
방법2. 커널 내부에 있는 각 공유 데이터에 접근할 때마다 그 데이터에 대한 lock/unlock
N개의 프로세스가 공유데이터를 동시에 사용하길 원하는 경우
각 프로세스의 Code Segment에는 공유데이터를 접근하는 코드인 Critical Section이 존재함
do {
entry section // 공유 데이터에 대한 lock을 건다.
critical section // 공유 데이터에 접근하기 위해 critical section에 들어옴
exit section // critical section을 나왔으므로, unlock을 한다. (다른 프로세스를 위해)
remainder section
} while(1);
임계구역 문제를 해결하기 위한 충족조건
Critical-section을 해결하기 위해서 만족해야 하는 조건은
(1). Mutual Exculsion(상호배제)
= 프로세스 P가 Critical Section에 들어가 있다면(코드를 수행중이라면), 다른 프로세스들은 Critical Section에 들어갈 수 없음
(2). Progress(진행)
= 아무도 Critical Section에 있지 않은 상태에서, Critical Section에 들어가고자 하는 프로세스가 있다면, Critical Section에 들어가게 해줘야 함
(3). Bounded Wating(유한대기)
= 프로세스가 Critical Section에 들어가려고, 요청한 후부터 그 요청이 허용될 때까지, 다른 프로세스들이 Critical Section에 들어가는 횟수에 한계가 있어야 함
(Ex. 3개의 프로세스가 있는데, 2개 프로세스들끼리만 왔다갔다 사용하고, 나머지 하나 프로세스는 Critical Section에 들어가지 못하는 상황)
Algorithm 1
int turn;
intitalize turn = 0; // P(i)는 critical section에 if(turn == i)면 들어감
P0
do {
while(turn != 0); // 내 차례가 아니면, 대기
critical section
turn = 1 // 이제 상대방(P1) 차례
remainder section
} while(1);
P1
do {
while(turn != 1); // 내 차례가 아니면, 대기
critical section
turn = 0 // 이제 상대방(P0) 차례
remainder section
} while(1);
이 알고리즘의 문제점
즉, 과잉양보 현상이 발생한다.
과잉양보
: 반드시 한 번씩 교대로 들어가야만 함 (swap-turn). 그가 turn 값을 내 값으로 바꿔 줘야만 내가 들어갈 수 있음. 특정 프로세스가 더 빈번히 critical section에 들어가야 한다면, 문제가 발생
Algorithm 2
Shared Data
boolean flag[2];
initialize flag[all] = false // 아직, 모든 프로세스는 critical section에 진입할 의사가 X
do {
flag[i] = true; // 나 들어가려고 한다.
while(flag[j]); // 다른 사람 있으면 기다릴게
critical section // critical section 들어와서 수행
flag[i] = false; // 나 다 끝났어. 깃발 내린다.
remainder section
} while(1);
이 알고리즘의 문제점
Algorithm 3 (Peterson`s Algorithm)
Algorithm 1,2를 통합하고, 순서를 잘 고려한 알고리즘
do{
flag[i] = true; // 나 들어가고 싶다.
turn = j; // 상대방 차례로 세팅
while(flag[j] && turn == j); // 상대방이 깃발(flag)도 들고, 들어갈 차례면 난 기다릴게
critical section
flag[i] = false; // 나 끝났어. 깃발 내린다.
remainder section
} while(1);
이 알고리즘 분석
앞선 방식들은 SW적인 처리방식의 가장 큰 특징인, 하나의 Instruction으로 처리 할 수 없어서 생긴 문제들이다.
이게 하나의 instruction으로 해결되면 간단히 lock걸고 해제할 수 있음 !
즉, 하드웨어적으로 하나의 (Test & modify를 atomic하게 수행할 수 있도록 지원하는) instruction만 주어지면 critical section문제는 쉽게 해결된다!
Mutual Exclusion with Test & Set
Sychronization variable
boolean lock = false;
P(i)에 대해서
do {
while(Test_and_Set(lock)); // lock 걸렸는지 체크하고, 아무도 없으면 내가 들어가기 전에 lock을 건다.( lock = false -> true )
critical section
lock = false;
remainder section
} while(1);
자료 출처