프로세스 동기화


 ◎ 배경

- 공유데이터에 대한 동시 접근은 데이터의 불일치를 초래 가능

=> 생산자-소비자 문제(Race-condition) 문제 발생

- 데이터의 일관성 유지를 위해 협력하는 프로세스들이 순차적으로 수행되어야만 함

- 이러한 Race-condition(경쟁조건)을 해결하기 위한 방법이 필요했음

- 경쟁조건이 발생하지 않으려면 한번에 하나의 스레드만 메모리에 접근 해야함

- 그래서 임계구역을 정의함


◎ 임계구역(Critical Section)

- 임계구역은 공유된 자원에 접근하기 위한 코드가 있는 곳을 의미

- 공유된 자원에 접근하는 것은 임계구역 진입을 의미

- 임계구역이 적용된 프로세스 구조

  1. do{
  2.     엔트리 섹션(임계구역에 진입하기위해 요청하는 코드 부분)
  3.     크리티컬 섹션
  4.     종료 섹션(임계구역에서 빠져나오기위해 요청하는 코드 부분)
  5.     리마인더 섹션(코드의 나머지 부분)
  6. }while(true);

임계구역 문제

-> 임계 구역으로 지정되어야 할 코드 영역이 임계 구역으로 지정되지 않았을 때 발생할 수 있는 문제

-> 이 문제는 "한번에 하나의 스레드만 메모리에 접근" 이라는 조건을 무시하게되어 경쟁조건이 발생


- 임계구역 문제의 해결 조건

-> 상호배제(Mutual exclusion)

어떤 프로세스가 임계구역이면 다른 프로세스는 임계구역에서 실행 불가

-> 진행(Progress)

임계구역에 프로세스가 없으면 임계구역에 들어가고 싶어하는 프로세스를 결정하는 것이 무한대로 지연되면 안됨

-> 한정된 대기(Bounded waiting)

다른 프로세스들이 임계구역에 들어가는 것이 허락되는 한계시간은 일정 시간으로 제한되어야 함

(자원을 요청한 스레드가 무한정 대기하지 않게 하는 것)


◎ 피터슨 솔루션(peterson's solution)

- 임계구역 문제를 해결하기 위해 개발됨

- 무조건 2개 프로세스에서만 가능

- 변수 2개를 공유

  - flag는 임계구역에 진입을 원하면 true, 아니면 false

  - turn은 프로세스 차례(정수형)


- 구조

■ 공유자원

  1. bool flag[0] = false;
  2. bool flag[1] = true;
  3. int turn;

■ 0번 프로세스 구조

  1. do{
  2.     flag[0] = true; // 0번 프로세스 플래그 true
  3.     turn = 1; // 1번 프로세스 차례
  4.     while(flag[1] && turn == 1){ // 1번 프로세스가 C.S에 입장하길 원하고 1번 프로세스 차례라면
  5.         // 1번 프로세스는 C.S
  6.         // 0번 프로세스는 대기(차례가 오거나 C.S에 있는 프로세스가 C.S를 사용 안하면 탈출)
  7.     }
  8.     // 대기 후 0번 프로세스 크리티컬 섹션 진입
  9.     [크리티컬 섹션 진입]
  10.     flag[0] = false; // C.S이 끝나면, 0번 프로세스는 false
  11. }while(true);


■ 1번 프로세스 구조

  1. do{
  2.     flag[1] = true; // 0번 프로세스 플래그 true
  3.     turn = 0; // 0번 프로세스 차례
  4.     while(flag[0] && turn == 0){ // 0번 프로세스가 C.S에 입장하길 원하고 0번 프로세스 차례라면
  5.         // 1번 프로세스는 C.S
  6.         // 0번 프로세스는 대기(차례가 오거나 C.S에 있는 프로세스가 C.S를 사용 안하면 탈출)
  7.     }
  8.     // 대기 후 0번 프로세스 크리티컬 섹션 진입
  9.     [크리티컬 섹션 진입]
  10.     flag[0] = false; // C.S이 끝나면, 0번 프로세스는 false
  11. }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밖에서 기다리던 무한정 기다리는 일은 없음.


결론 : 만족한다. 하지만 아직 문제점은 있다.