프로세스 동기화

 

동시다발적으로 실행되는 프로세스들은 서로 협력하며 영향을 주고 받는다

그러므로  프로세스들의 동기화를 고려해야 한다

 

 

 

동기화란?


  • 프로세스들의 수행 시기를 맞추는 것
    • 실행 순서 제어 : 프로세스를 올바른 순서대로 실행하기
    • 상호 배제 : 동시에 접근해서는 안되는 자원에 하나의 프로세스만 접근하게 하기
  • 공동의 목적을 위해 동시다발적으로 수행되는 프로세서들은 자원의 일관성을 유지하며 실행되어야 함
    그래서 동기화가 필요함
    • ex) 워드프로세서 : 맞춤법 검사, 읽기, 출력 등 다양한 프로세스들이 동시에 실행
      각각 움직이면 안됨
  • 실행의 문맥을 갖는 모든 대상은 동기화 대상이기에 스레도드 동기화 대상임

 

 

 

동기화를 하지않으면 발생하는 대표적인 문제


 

실행 순서 제어를 위한 동기화 : reader writer problem

  • Writer : Book.txt 파일에 값을 저장하는 프로세스
  • Reader : Book.txt 파일에 저장된 값을 읽어드리는 프로세스

 

  • Reader 프로세스는 'Book.txt' 안에 값이 존재한다는 특정 조건이 만족되어야만 실행 가능
  • 따라서 아무렇게나 실행되어선 안되고 실행의 순서를 지켜야 함(Writer -> Reader)
  • 이렇듯, 동시다발적으로 실행되는 두 개 이상의 프로세스가 있을 때 실행 순서를 제어하도록 동기화 해주는 것이 실행 순서 제어를 위한 동기화임

 

 

 

상호 배제를 위한 동기화 : Bank account problem

  • 공유 불가능한 자원의 동시 사용을 피하기 위한 동기화
  • 한 번에 하나의 프로세스만 접근해야 하는 자원에 동시 접근을 피하기 위한 동기화
  • 예시
    • 현재 계좌 잔액 10만원
    • 프로세스 A : 현재 잔액에 2만원을 추가하는 프로세스
    • 프로세스 B : 현재 잔액에 5만원을 추가하는 프로세스
    • 동기화 없이 실행했을 때 실제 실행 결과

 

  • 동기화를 적용한 실행 결과

 

 

 

 

Producer & Consumer problem

  • 물건을 계속해서 생산하는 생산자(producer, 프로세스 혹은 스레드)
  • 물건을 계속해서 소비하는 소비자(consumer, 프로세스 혹은 스레드)
  • '총합' 변수를 공유하는 상황에서 발생하는 생산자-소비자 문제 
  • 예시

  • 이 상태에서 생산자를 10만번, 소비자를 10만번 실행하면 총합 값은
    0과 다른 값이 되거나 오류가 발생해버림
    => 동기화가 되지 않아 발생한 문제. 즉, 동시에 접근해서는 안 되는 자원에 동시에 접근했기 때문 

 


 

 

공유 자원과 임계 구역


  • 그렇다면 동시에 접근해서는 안되는 자원이 뭘까?
  • 공유 자원(Shared Resource) & 임계 구역(Critical Section)
  • 공유 자원 : 여러 프로세스 혹은 스레드가 공유하는 자원을 의미
    •  전역 변수, 파일, 입출력장치, 보조기억장치 등등..
    • 생산자, 소비자 이 두 개의 프로세스가 "총합"이라고 하는 변수를 공유 => 공유 자원이라고 할 수 있음
  • 임계 구역 : 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
    • 앞선 예시의 '총합' 변수, '잔액' 변수 등에 접근하는 코드(읽기, 더하기 등등)
    • 공유 자원에 접근하는 코드 중 동시에 실행하면 문제가 발생하는 코드 영역 

 

 

  • 임계 구역에 진입하고자 하면 진입한 프로세스 이외에는 대기해야 함
  • 레이스 컨디션(race condition) : 임계 구역에 동시에 접근하여 자원의 일관성이 깨진 상태 
    • 앞의 3개의 사례(읽기 쓰기, 은행 계좌, 생산자 소비자 문제) 모두 레이스 컨디션이라고 할 수 있음

 

  • C, Python과 같은 고급 언어는 컴퓨터 내부에서 실행될 때 저급 언어로 변환됨

  • 그래서 1줄의 소스코드여도 내부에서 변환을 하면 한 줄이 아님 
  • 그래서 내부에서 실행 중 문맥교환이 일어나면 총합을 1씩 증감하는 간단한 코드도 예상치못한 결과가 발생할 수 있음
  • 그러므로 운영체제는 임계구역에서 자원의 일관성이 깨지지 않도록(레이스 컨디션이 발생하지 않도록) 관리 해야함

 

 

상호 배제를 위한 동기화를 위한 3가지 원칙

1. 상호 배제 (mutual exclusion)

  • 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 들어올 수 없음

 

2. 진행(progress)

  • 임계 구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 들어갈 수 있어야 함

 

3. 유한 대기(bounded wating)

  • 한 프로세스가 임계 구역에 진입하고 싶다면 언젠가는 임계 구역에 들어올 수 있어야 함
  • 임계 구역에 들어오기 위해 무한정 대기해서는 안됨

 

 


 

동기화 기법

  • 여러가지가 있지만 대표적인 3가지
    • 뮤텍스 락, 세마포, 모니터

 

 

뮤텍스 락


  • 상호 배제를 위한 동기화 도구 
  • 탈의실에 있는 자물쇠 같은 역할 
    • 손님은 프로세스, 탈의실 내부는 임계구역
    • 자물쇠를 통해 진행중인 프로세스가 있는지 확인하고 실행 

 

뮤텍스 락 형태

  • 전역 변수 하나, 함수 두개
  • 자물쇠 역할 : 프로세스들이 공유하는 전역 변수 lock(boolean)
  • 임계 구역을 잠그는 역할 : acquire 함수
    • 프로세스가 임계 구역에 진입하기 전에 호출
    • 임계 구역이 잠겨 있다면
      임계 구역이 열릴 때까지 (lock이 false가 될 때까지) 임계 구역을 반복적으로 확인
    • 임계 구역이 열려있다면
      임계 구역을 잠그기(lock을 true로 바꾸기)
  • 임계 구역의 잠금을 해제하는 역할 : release 함수 
    • 임계 구역에서의 작업이 끝나고 호출
    • 현재 잠긴 임계 구역을 열기(lock을 false로 바꾸기)
  • 임계 구역 접근이 필요하면 acquire 함수 호출 → 임계 구역이 잠겨있다면 열릴 때까지 반복 확인 → 열리면 lock을 true로 자물쇠를 잠근 뒤 코드에 접근 → 볼일 다 보면 release 함수 호출 → 잠긴 임계구역 열기(lock = false)

 

코드 구현

  • 간단히 구현한 것으로 실제로는 더 길고 복잡함
  • 프로그래밍 언어에서도 지원해주는 경우도 있음 

 

 

 

위에서 봤던 생산자-소비자 문제를 봤을 때 아래 코드와 같음

acquire();
// '총합' 변수 접근
release();

 

 

바쁜 대기(busy waiting)

  • 무한히 대기하면서 반복적으로 임계구역이 열려있는지 아닌지를 확인해 보는 것
  • 탈의실이 비었나 문을 계속 덜컹거리며 열어보려 하는 것과 같음 
  • CPU 사이클 낭비!

 

 

참고) 스핀락(spinlock) - 강의 QnA

  • 뮤텍스락과 비슷(while문 내부를 반복하며 lock을 확인)
  • 뮤텍스락은 뒤에 나올 세미포(semaphore)처럼 대기상태 + 큐를 사용하지만 스핀락은 사용 안함
  • 보통 스핀락은 스핀락이라고 명시되어 있음
  • 구체적인 구현은 구현체에 따라 다를 수 있음 

 

 


세마포(semaphore)

  • 좀 더 일반화된 방식의 동기화 도구
  • 공유 자원이 여러 개 있는 경우에도 적용 가능
  • 상호 배제를 위한 동기화뿐만 아니라 실행 순서를 위한 동기화도 제공
    (실행 순서를 위한 동기화는 아래에서 알아볼 예정)
  • 세마포의 종류로는 이진 세마포와 카운팅 세마포가 있음
    • 이진 세마포는 뮤테스락과 비슷하기 때문에 뒤에서 설명하는 건 카운팅 세마포임

 

  • 세마포라는 단어는 철도 신호를 의미함
  • 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리기
  • 임계 구역 앞에서 가도 좋다는 신호를 받으면 임계 구역 진입 

 

 

 

세마포의 형태

  • 전역 변수 하나, 함수 두개
  • 전역 변수 S : 임계 구역에 진입할 수 있는 프로세스의 개수(사용 가능한 공유 자원의 개수)
  • wait 함수 : 임계 구역에 들어가도 좋은지, 기다려야 할지를 알려주는 함수
  • signal 함수 : 임계 구역 앞에서 기다리는 프로세스에 '이제 가도 좋다'고 신호를 주는 함수
  • 전공서마다 함수 명은 다름 
  • 임계구역 앞뒤로 wait과 signal 함수 호출 
wait()
// 임계 구역
signal()

 

 

 

코드 구현

 

 

 

 

 

예시

  • 세 개의 프로세스 P1, P2, P3가 두 개의 공유 자원(S=2)에 P1,P2,P3 순서로 접근한다고 가정

 

 

 

바쁜 대기

  • 세마포 역시 바쁜 대기가 발생할 수 있음

 

 

바쁜 대기 해결 방법

  • 사용할 수 있는 자원이 없을 경우 대기 상태로 만듦
    (해당 프로세스의 PCB를 대기 큐에 삽입)
  • 사용할 수 있는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태로 만듦
    (해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입)

 

 

코드 구현(sudo code)

 

 

예시

  • 세 개의 프로세스 P1, P2, P3가 두 개의 공유 자원(S=2)에 P1,P2,P3 순서로 접근한다고 가정

 

 

세마포의 실행 순서 동기화

  • 실행 순서 동기화를 하기 때문에 순서를 보장할 수 있음
  • 방법
    • 세마포의 변수 S를 0으로 두고
    • 먼저 실행할 프로세스 뒤에 signal 함수
    • 다음에 실행할 프로세스 앞에 wait 함
  • P1이 먼저 실행되면 실행 순서 ok
  • P2가 먼저 실행되더라도 wait에 걸리고 S가 -1이 되어 대기 큐에 삽입되므로 P1이 먼저 실행됨 

 

 


 

 

 

모니터


  • 세마포는 매번 임계구역 앞뒤로 함수를 호출해야하기 때문에 번거로움과 실수의 위험이 큼 
  • 그래서 사용자(개발자)가 다루기에 편한 동기화 도구인 "모니터" 가 생김
  • 모니터를 활용하는 대표적인 프로그래밍 언어로는 JAVA가 있음 
  • 모니터는 상호 배제를 위한 동기화와 실행 순서 제어를 위한 동기화 두 가지를 모두 제공 

 

 

모니터의 상호 배제를 위한 동기화

  • 공유 자원과 공유 자원에 접근하기 위한 통로를 묶어서 관리
    • 인터페이스를 위한 큐
    • 공유 자원에 접근하고자 하는 프로세스를 (인터페이스를 위한) 큐에 삽입
    • 큐에 삽입된 순서대로 (한 번에 하나의 프로세스만) 공유 자원 이용 
  • 공유 자원에 접근하고자 하는 프로세스와 스레드는 반드시 특정 인터페이스를 통해 접근해야 함 

 

 

 

실행 순서 제어를 위한 동기화

  1. 특정 프로세스가 아직 실행될 조건이 되지 않았을 때에는 wait을 통해 실행을 중다
  2. 특정 프로세스가 실행될 조건이 충족되었을 때에는 signal을 통해 실행을 재개 
  • 조건 변수(condition variable) 이용
    • 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수
    • wait이나 signal이라고 함수를 호출할 수 있는 특별한 변수
      • 조건변수.wait() : 대기 상태로 변경, 조건 변수에 대한 큐에 삽입
      • 조건변수.signal() : wait으로 대기 상태로 접어든 조건 변수를 실행 상태로 변경
    • 각각의 조건 변수에 대한 큐로 실행 순서를 제어함 
  • 조건 변수에 대한 큐는 앞에서 말한 상호 배제를 위한 큐와 다름 

 

  • 프로세스 내에서 조건 변수 x에 대해 wait 함수 호출 
    → 조건 변수 x에 대한 큐에 프로세스 삽입(대기 상태로 변경) 

 

  • 모니터 안에는 하나의 프로세스만 있을 수 있음
  • siganl호출 방식에는 아래 두 가지가 있음 
    • wait()을 호출했던 프로세스는 signal()을 호출한 프로세스가 모니터를 떠난 뒤에 수행을 재개
    • signal()을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal()을 호출한 프로세스의 수행을 재개 
    • 선점/비선점과 비슷하지만 별개의 개념임. wait을 해도 문맥 교환이 일어날 수 있음 

 

 

 

 

출처 : 혼자 공부하는 컴퓨터구조 + 운영체제 (저자 강민철)