OS 12 - 프로세스 동기화

12-1 동기화란

동기화의 의미

프로세스들은 서로 협력하며 영향을 주고 받기도 한다. 협력하여 실행되는 프로세스들은 실행 순서와 자원의 일관성을 보장해야 하기 때문에 동기화 되어야 한다.

프로세스 동기화 란 프로세스들 사이의 수행 시기를 맞추는 것이다. 프로세스 동기화에는 실행 순서 제어를 위한 동기화와 상호 배제를 위한 동기화가 있다.

실행 순서 제어를 위한 동기화 는 프로세스를 올바른 순서대로 실행하기 위한 동기화이다. 예를 들어, 읽기와 쓰기라는 프로세스가 존재할 때, 읽기 프로세스는 쓰기 프로세스가 끝나야 실행할 수 있기 때문에 프로세스를 올바른 순서대로 실행해야 한다.

상호 배제를 위한 동기화 는 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하게 하기 위한 동기화이다. 예를 들어, 두 개의 프로세스가 한 개의 자원에 동시에 접근하여 값을 바꾸려고 한다면 원하던 바와 다른 값이 나올 수 있다. 이를 막기 위해 존재하는 것이 바로 상호 배제를 위한 동기화이다.

상호 배제를 위한 동기화를 위해서는 세 가지 원칙이 지켜져야 한다.

  • 상호 배제 : 임계 구역에는 하나의 프로세스만 접근할 수 있다.
  • 진행 : 임계 구역에 어떤 프로세스도 진입하지 않았다면 임계 구역에 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
  • 유한 대기 : 임계 구역에 들어오기 위해 무한정 대기해서는 안 된다.

공유 자원과 임계 구역

동시에 실행되는 프로세스들이 공동의 자원을 두고 작업을 할 때, 공동의 자원을 공유 자원 이라고 한다.

동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역을 임계 구역 이라고 한다. 임계 구역에는 하나의 프로세스만 접근이 가능하다.

잘못된 실행으로 여러 프로세스가 동시 다발적으로 임계 구역의 코드를 실행하여 문제가 발생하는 상황을 레이스 컨디션 이라고 한다.

12-2 동기화 기법

뮤텍스 락 (Mutex Lock: MUTual EXclusion lock)

동시에 접근해서는 안 되는 자원에 동시에 접근하지 않도록 만드는 도구이다.

  • 자물쇠 역할 : 프로세스들이 공유하는 전역 변수 lock
    • 임계 구역이 잠겨있다 == (lock = true)
    • 임계 구역이 열려있다 == (lock = false)
  • 임계 구역을 잠그는 역할 : acquire 함수
    • 프로세스가 임계 구역에 진입하기 전에 호출하는 함수
    • 임계 구역이 잠겨 있다면 열릴 때까지 반복적으로 확인하고, 임계 구역이 열려 있다면 임계 구역을 잠그는 함수
  • 임계 구역의 잠금을 해제하는 역할 : release 함수
    • 임계 구역에서 작업이 끝나고 호출하는 함수
    • 현재 잠긴 임계 구역을 열어주는 함수

acquire은 반복적으로 lock을 확인하는데, 이러한 대기 방식을 바쁜 대기라고 한다.

세마포(Semaphore)

뮤텍스 락이 하나의 공유 자원에 접근하는 프로세스를 상정한 방식이라면, 세마포는 공유 자원이 여러 개 있을 경우에 사용되는 도구이다.

  • 공유 자원의 개수를 나타내는 전역 변수 S
  • 임계 구역에 들어가도 좋은지, 기다려야 할지를 알려주는 wait 함수
  • 임계 구역 앞에서 기다리는 프로세스에게 가도 좋다는 신호를 주는 signal 함수

사용할 수 있는 공유 자원이 없는 경우 프로세스는 무작정 무한히 반복하며 S를 확인해야 한다. 이는 바쁜 대기라고 할 수 있는데, CPU 주기를 낭비한다는 점에서 손해이다.

그래서 세마포는 더 좋은 방법을 사용한다. 공유 자원이 없을 경우,

  1. 해당 프로세스 상태를 대기 상태로 만든다
  2. 프로세스의 PCB를 세마포를 위한 대기 큐에 넣는다.
  3. 다른 프로세스가 임계 구역에서의 작업이 끝나고 signal 함수를 호출하면
  4. signal 함수는 대기 중인 프로세스를 대기 큐에서 제거하고, 프로세스 상태를 준비 상태로 변경한 뒤 준비 큐로 옮겨준다.

세마포를 이용하면 동시에 실행되는 프로세스의 실행 순서도 제어할 수 있다.

프로세스가 먼저 실행되더라도, wait 함수를 만나면 다른 프로세스가 먼저 임계 구역에 진입하게 된다. 해당 프로세스가 임계 구역의 실행을 끝내고 signal을 호출하면 그제서야 먼저 실행된 프로세스가 임게 구역에 진입할 수 있다.

모니터

모니터는 공유 자원과 공유 자원에 접근하기 위한 인터페이스(통로)를 묶어 관리한다. 프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근할 수 있도록 한다.

  1. 모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입한다.
  2. 큐에 삽입된 순서대로 하나씩 공유 자원을 이용하도록 한다.

모니터는 특정 조건을 바탕으로 프로세스를 실행하고 일시 중단하기 위해 조건 변수 를 사용한다. 조건 변수는 프로세스의 실행 순서를 제어하기 위한 변수이다. 조건 변수로는 wait와 signal 연산을 수행할 수 있다.

  1. 모니터에 진입한 프로세스가 x.wait()를 통해 조건 변수 x에 대한 wait를 호출한다.
  2. 프로세스는 조건 변수 x에 대한 큐에 삽입된다.
  3. 이로 인해, 모니터는 다시 빈 상태가 된다.
  4. 공유 자원 인터페이스를 위한 큐에 있던 다른 프로세스가 모니터로 들어온다.
  5. signal 연산이 실행되면 wait으로 인해 대기 상태로 큐에 삽입되어 있던 프로세스가 깨어나 다시 모니터 안으로 들어올 수 있다.
  • 특정 프로세스가 아직 실행될 조건이 되지 않았을 때는 wait을 통해 실행을 중단한다
  • 특정 프로세스가 실행될 조건이 충족되었을 때는 signal을 통해 실행을 재개한다