프로세스 동기화
프로세스 동기화란
하나의 자원을 한 순간에 하나의 프로세스만이 이용하도록 제어하는 것
스레드 동기화란
하나의 코드블록 또는 메소드를 한순간에 하나의 스레드만이 이용하도록 보장하는 것
동기화가 없다면
- 데이터 일관성이 깨짐 => 즉, 한 순간 하나의 데이터의 값이 여러개일 수도 있게 됨, 다시 말해 여러개의 스레드가 하나의 변수에 대한 값이 제각각일 수 있게 됨.
배경
협력적 프로세스는 시스템 내에서 실행중인 다른 프로세스의 실행에 영향을 주거나 받는 프로세스 이다. 협력적 프로세스는 논리 주소 공간(코드, 또는 데이터)를 직접 공유
하거나 파일 또는 메시지
에 의해서 공유가 이루어진다 전자의 방법을 통해 논리 주소 공간을 공유하는 것은 스레드(Thread)
를 통해 달성할 수 있다. 하지만 이러한 경우 데이터의 비일관성
을 초래할 수 있다. 때문에 데이터의 일광성을 유지
하기 위해 프로세스 동기화가 필요하다.
예시
생산자 소비자 문제
를 예시로 들겠다. 유한 버퍼에 데이터를 생산하는 생산자
와 그 데이터를 소비하는 소비자
가 존재한다. 생산자, 그리고 소비자에 대한 설명은 아래와 같다
생산자
생산자
는 아이템 수를 나타내는 Count
값이 buffer size
와 같다면 여유 공간이 생기기 전까지 while문을 돌며 sleep한다. 또한 여유 공간이 생긴 경우 아이템을 생성하며 Count
를 1증가 시킨다.
소비자
소비자
는 buffer
에 아무런 데이터가 없다면 while문을 돌며 sleep한다. 또한 버퍼에 데이터가 존재한다면 그 데이터를 소비하여 Count
를 1감소 시킨다.
이 두 생산자, 소비자는 개별적으로 실행시 적절히 동작하지만 병렬적으로 실행하는 경우는 그렇지 못하다. 예를 들어 counter
의 값이 5일때 생산자, 소비자 코드를 동시에 실행하는 경우 counter
의 결과는 4가 될수도 6이 될수도 있다. 이러한 상황이 발생하는 이유는 단 한줄의 코드인 counter++ 또는 counter--
조차도 원자적으로 실행되지 않기 때문이며, 또한 counter
의 변수에 두 프로세스가 동시에 조작하도록 허용했기 때문이다.
*경쟁상황 - 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황
임계구역(Critical Section)
do {
*entry section*
critical section
*exit section*
remainder section
}while(TRUE);
공유 자원에 접근하는 코드의 일부를 말한다. 각 프로세스는 자신의 임계구역으로 진입하려면 진입 허가를 요청해야 한다. 이런 요청 부분을 entry section
이라고 한다. 또한 임계구역(Critical Section)
에서 코드 실행을 마친 후 임계구역을 나오기전 실행해야하는 코드가 있는데 이런 부분을 exit section
이라고 한다.
임계구역 문제
임계 구역으로 지정되어야 할 코드 영역이 임계구역으로 지정되지 않았을 때 발생할 수 있는 문제
임계구역 문제 해결조건
임계구역 문제를 해결하기 위해서는 아래의 3가지 조건을 모두 충족해야 한다.
상호배제(mutual exclusion)
- 한 프로세스가 임계구역에서 실행중이라면 다른 프로세스들은 그들 자신의 임계구역에서 실행될 수 없다.
진행(Progress)
- 임계구역에 들어간 프로세스가 없는 상태에서 들어가려는 프로세스가 여러 개 있다면 어느 것이 들어갈지 적절히 결정해야 한다. 또한 이 선택은 무한정 연기되면 안된다.
한정된 대기(Bounded waiting)
- 다른 프로세스의 기아를 방지하기 위해, 한 번 임계 구역에 들어간 프로세스는 다음 번 임계 구역에 들어갈 때 제한을 두어야 한다.
- 진행과 착각할 수 있는데 진행은 말그대로 임계구역 해결을 위해 코드 실행이 멈추지 않는 것을 의미하며 한정된 대기는 임계구역 코드 실행에 들어간 프로세스 외 나머지 프로세스들이 기아 현상이 나타나지 않도록 하기 위해
이미 임계구역을 실행한 프로세스를 제한하는 것
을 의미한다.
임계구역 문제 해결책
피터슨의 해결안
피터슨의 해결안은 두 개의 프로세스
에 대한 소프트웨어 기반
의 바쁜 대기(Busy Wating)
를 사용하는 임계구역 문제 해결책이다. 프로세스는 P0과 P1로 번호를 매긴다. 편의상 Pi 라고 표현하면 Pj는 다른 프로세스를 가리키고 j는 1-i와 같다. 피터슨 해결안은 두 개의 프로세스가 아래 두 개의 데이터항목(turn, flag
)을 공유하도록하여 임계구역 문제를 해결한다.
xxxxxxxxxx
int turn;
boolean flag[2];
- 변수 turn
은 임계구역으로 진입할 순번을 나타낸다. 즉, turn == i
라면 Pi가 임계구역에서 실행될 수 있다.
- flag
배열은 프로세스가 임계구역으로 진입할 준비가 되었다는 것을 나타낸다. 예를 들어 flag[i]가 참이라면 Pi가 임계구역으로 진입할 준비가 되었다는 것을 나타낸다.
xxxxxxxxxx
*피터슨 해결안의 Process Pi의 구조*
do {
// ===== entry section start =====
flag[i] = true;
turn = j;
while(flag[j] && turn == j);
// ===== entry section end =====
*critical section*
// ===== exit section start =====
flag[i] = false;
// ===== exit section end =====
*remainder section*
}while(true);
임계구역 문제를 해결하기 위해서 앞선 3가지 조건을 해결해야 함을 말했다.
1. 상호배제
첫 번째 while문의 조건이 flag[j] && turn == j
임을 통해 상호배제가 이루어짐을 알 수 있다. 두개의 프로세스가 동시에 critical section
에서 수행이 이루어지고 있다면 flag[0] == flag[1] == true
로 지정이 되어있어야 한다. 또한 turn == 0 == 1
이 어야 두 개의 프로세스가 critical section
에서 동시에 수행이 가능한 것인데 turn
은 한순간에 오직 1개의 값만을 가질 수 있으므로 상호배제가 이루어짐을 알 수 있다.
2. 진행
Pj가 임계구역에 진입할 준비가 되지 않았다면 flag[j] == false
일 것 이며, 따라서 Pi의 entry section
의 while(flag[j] && turn == j);
조건에서 flag[j]가 false이므로 Pi는 임계구역에 진입이 가능할 것이다. 이로써 진행의 조건을 만족할 수 있다.
3. 한정된 대기
Pj가 flag[j]=true
를 실행한 뒤 while문을 실행하면 이때 turn == i
또는 turn == j
일 것이다. i라면 Pi가 j라면 Pj가 임계구역에 진입한다. 이 때 turn == j
라고 가정하여 Pj가 실행되었다면 추 후 exit section
의 flag[j] = false
를 실행하게 되며 Pi가 임계구역에 진입하도록 해준다. 또한 Pj가 다시 실행하게 되어 flag[j] = true
를 실행하면 반드시 turn = i
를 실행하게 되므로 Pi가 실행을 위해 while문에서 대기중이었다면 Pi도 반드시 한번은 임계구역에 진입할 수 있도록 보장하게 된다.
바쁜 대기(Busy Waiting)
바쁜 대기란 특정 공유자원에 대해 두 개 이상의 프로세스나 스레드가 이용 권한을 획득하고자 하는 동기화 상황에서 무한 루프
를 돌며 쓸데 없이 CPU 자원을 낭비하며 대기하는 현상을 말한다. 대신 뮤텍스(Mutex) 나 세마포어(Semaphore)
등을 사용하면 바쁜 대기를 하지 않을 수 있다. 하지만 바쁜대기
는 뮤텍스 또는 세마포어를 사용하기에는 오버헤드가 큰 상황에서 간단히 사용할 수 있다.
'CS(Computer Science) > 운영체제' 카테고리의 다른 글
프로세스간 통신(IPC) - 수정중 (0) | 2018.11.18 |
---|---|
스레드 개요 (0) | 2018.10.06 |
프로세스 스케줄링 (0) | 2018.09.24 |
프로세스 개요 (0) | 2018.09.11 |
메모리관리(메모리 낭비 방지) (0) | 2018.09.06 |