프로세스 동기화
◎ 배경
- 공유데이터에 대한 동시 접근은 데이터의 불일치를 초래 가능
=> 생산자-소비자 문제(Race-condition) 문제 발생
- 데이터의 일관성 유지를 위해 협력하는 프로세스들이 순차적으로 수행되어야만 함
- 이러한 Race-condition(경쟁조건)을 해결하기 위한 방법이 필요했음
- 경쟁조건이 발생하지 않으려면 한번에 하나의 스레드만 메모리에 접근 해야함
- 그래서 임계구역을 정의함
◎ 임계구역(Critical Section)
- 임계구역은 공유된 자원에 접근하기 위한 코드가 있는 곳을 의미
- 공유된 자원에 접근하는 것은 임계구역 진입을 의미
- 임계구역이 적용된 프로세스 구조
- do{
- 엔트리 섹션(임계구역에 진입하기위해 요청하는 코드 부분)
- 크리티컬 섹션
- 종료 섹션(임계구역에서 빠져나오기위해 요청하는 코드 부분)
- 리마인더 섹션(코드의 나머지 부분)
- }while(true);
- 임계구역 문제
-> 임계 구역으로 지정되어야 할 코드 영역이 임계 구역으로 지정되지 않았을 때 발생할 수 있는 문제
-> 이 문제는 "한번에 하나의 스레드만 메모리에 접근" 이라는 조건을 무시하게되어 경쟁조건이 발생
- 임계구역 문제의 해결 조건
-> 상호배제(Mutual exclusion)
어떤 프로세스가 임계구역이면 다른 프로세스는 임계구역에서 실행 불가
-> 진행(Progress)
임계구역에 프로세스가 없으면 임계구역에 들어가고 싶어하는 프로세스를 결정하는 것이 무한대로 지연되면 안됨
-> 한정된 대기(Bounded waiting)
다른 프로세스들이 임계구역에 들어가는 것이 허락되는 한계시간은 일정 시간으로 제한되어야 함
(자원을 요청한 스레드가 무한정 대기하지 않게 하는 것)
◎ 피터슨 솔루션(peterson's solution)
- 임계구역 문제를 해결하기 위해 개발됨
- 무조건 2개 프로세스에서만 가능
- 변수 2개를 공유
- flag는 임계구역에 진입을 원하면 true, 아니면 false
- turn은 프로세스 차례(정수형)
- 구조
■ 공유자원
- bool flag[0] = false;
- bool flag[1] = true;
- int turn;
■ 0번 프로세스 구조
- do{
- flag[0] = true; // 0번 프로세스 플래그 true
- turn = 1; // 1번 프로세스 차례
- while(flag[1] && turn == 1){ // 1번 프로세스가 C.S에 입장하길 원하고 1번 프로세스 차례라면
- // 1번 프로세스는 C.S
- // 0번 프로세스는 대기(차례가 오거나 C.S에 있는 프로세스가 C.S를 사용 안하면 탈출)
- }
- // 대기 후 0번 프로세스 크리티컬 섹션 진입
- [크리티컬 섹션 진입]
- flag[0] = false; // C.S이 끝나면, 0번 프로세스는 false
- }while(true);
■ 1번 프로세스 구조
- do{
- flag[1] = true; // 0번 프로세스 플래그 true
- turn = 0; // 0번 프로세스 차례
- while(flag[0] && turn == 0){ // 0번 프로세스가 C.S에 입장하길 원하고 0번 프로세스 차례라면
- // 1번 프로세스는 C.S
- // 0번 프로세스는 대기(차례가 오거나 C.S에 있는 프로세스가 C.S를 사용 안하면 탈출)
- }
- // 대기 후 0번 프로세스 크리티컬 섹션 진입
- [크리티컬 섹션 진입]
- flag[0] = false; // C.S이 끝나면, 0번 프로세스는 false
- }while(true);
※ 피터슨 솔루션은 임계구역 문제 해결 요구사항에 만족하는가?
- 상호배제(Mutual exclusion)
- 두가지경우(두 프로세스 모두 원함)
- 0,1번 프로세스가 C.S 진입을 원하고 0번 차례 일때
- flag[0] = true, flag[1] = true, turn = 0
- 0번 프로세스는 flag[1] && turn == 1 조건이면, 0번 프로세스 C.S
- 1번 프로세스는 flag[0] && turn == 0 조건이므로, 1번 프로세스 대기
- 0,1번 프로세스가 C.S 집입을 원하고 1번 차례 일때
- flag[0] = true, flag[1] = true, turn = 1
- 0번 프로세스는 flag[1] && turn == 1 조건이면, 0번 프로세스 대기
- 1번 프로세스는 flag[0] && turn == 0 조건이므로, 1번 프로세스 C.S
따라서 turn 변수는 하나의 값만 가지므로 무조건 C.S에는 한 프로세스 만 존재하게 되어 이 조건에 충족
- 진행(Progress)
크리티컬 섹션에 진입하고 끝나게 되면 flag[0] = false; 또는 flag[1] = true; 처럼 무조건 flag를 원래 상태로 바꾸기 때문에 기다리던 프로세스가 무조건 C.S로 진입하게 되어 이 조건에 충족
- 한정된 대기(Bounded waiting)
특정 프로세스가 임계구역을 나옴과 동시에 진행 요구사항에서 말한 것처럼 flag가 변함과 동시에 기다리던 프로세스가 C.S로 들어가므로, C.S밖에서 기다리던 무한정 기다리는 일은 없음.
결론 : 만족한다. 하지만 아직 문제점은 있다.