아래 3가지 조건을 모두 만족해야한다.
Mutual Exclusion(상호 배체)
Progress(진행)
Bounded Waiting(유한대기)
가정
do{
entry section
critical section
exit section
remainder section
}while(1)
synchronization variable
int turn;
initially turn = 0
do{
while(turn!=0); /* My turn? */
critical section
turn = 1; /* Now its your turn */
remainder section
}while(1)
이는 과잉 양보 를 하게 되어 발생한 문제이다. 위 로직에 따르면 반드시 한 번씩 교대로 들어가햐만 하는데 (swap-turn). 결국 상태가 turn 값을 내 값으로 바꿔줘야만 내가 들어갈 수 있다. 만약 특정 프로세스는 critical section이 없어서 turn이 업데이트 될 일이 없는데 또다른 특정 프로세스는 매우 빈번히 critical section을 들어가야 한다면 ? 이럴 때 progress 조건을 만족시키지 못하는 것이다.
synchronization variable
boolean flag[2]
flag[모두] = false
flag[i] == true
라면 Pi는 critical section에 들어간 것임Progress Pi
do{
flag[i]=true; /*Pretend I am in */
while(flag[j]); /*Is he also in? then wait */
critical section
flag[i]=false; /*I am out not */
remainder section
}while(1)
mutual exlusion을 만족시킨다 (+)
여전히 progress를 만족시키지 못한다 (-)
why?
두 프로세스 다 2행까지 수행 후 끊임 없이 양보하는 상황이 발생할 수 있기 때문이다.ex) flag를 true로 바꾼 상태에서 critical section 영역에 들어가려는 찰나에 CPU 제어권이 뺏기게 되는 경우, 다른 프로세스가 자신의 flag를 true로 바꾸어 의사표시를 했음에도 while문이 영원히 수행되면서 아무도 critical section을 사용하지 않음에도 들어가지 못하는 상황이 발생할 수 있다 (=서로가 깃발로 의사표시는 하였는데 아무도 못들어가는 상태)
do{
flag[i]=true; /*My intentions is to enter... */
turn =j /*Set to his turn */
while (flag[i] && turn ==j); /* wait only if... */
critical section
flag[i] = false
remainder section
}while(1);
Test & modify
를 atomic하게 수행할 수 있도록 지원하는 경우 앞의 문제는 간단히 해결됨boolean lock = false;
do{
while(Test_and_Set(lock));
critical section
lock = false;
remainder section
}
Semaphore S
P(S)
(자원 획득 과정) : while(S<=0) do no-op; S--;
V(S)
(자원 반납 과정) : s++;
semaphore mutex; /* initially 1: 1개가 CS에 들어갈 수 있다 */
do{
P(mutex); /* If positive, dec-&-enter, Otherwize,, wait */
critical section
V(mutex); /* Increment semaphore */
remainder section
}while (1);
typedef struct{
int value; /*semaphore */
struct process *L /*process wait queue */
} semaphore
block과 wakeup을 다음과 같이 가정
block
wait queue
에 넣음wakeup(P)
참고 사진
S.value--; /*prepare to enter */
if(S.value<0) /*Oops, negative, I cannot enter */
{
add this process to S.L; /* block시키지 전에 대기 큐에 넣어둠 */
block();
}
S.value++;
if (S.value <=0){
remove a process P from S.L;
wakeup(P);
}
Busy-wait
vs Block/wakeup