CS/운영체제

[CS/운영체제] 프로세스의 동기화

NLP Developer 2024. 1. 30. 17:42
728x90
반응형

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

이 과정에서 자원의 일관성을 보장해야 한다.

-> 자원의 일관성을 보장하기 위해서 프로세스들의 동기화를 고려해야 한다.

1. 동기화의 의미

공동의 목적을 위해 동시에 수행되는 프로세스

 

ex) 워드 프로세서 프로그램

  • 맞춤법 검사 프로세스
  • 입력 내용을 화면에 출력하는 프로세스
이렇게 막 실행해도 괜찮은가? 
-> No. 올바른 수행을 위해 프로세스들은 동기화되어야 한다.

 

(1) 프로세스 동기화란?

프로세스 동기화란 프로세스들의 수행 시기를 맞추는 것이다.

이는 크게 두 가지를 의미한다.

  1. 실행 순서 제어 : 프로세스를 올바른 순서대로 실행하기
  2. 상호 배제 : 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하게 하기

-> 실행의 문맥을 갖는 모든 대상은 동기화 대상이기에 스레드도 동기화 대상이다.

1) 실행 순서 제어를 위한 동기화 : reader write problem

Writer : Book.txt 파일에 값을 저장하는 프로세스

Reader : Book.txt 파일에 저장된 값을 읽어들이는 프로세스

Reader와 Writer 프로세스는 무작정 아무렇게나 실행되어선 안된다. -> 실행의 순서가 있기 때문

Reader 프로세스는 'Book.txt 안에 값이 존재한다'는 특정 조건이 만족되어야만 실행 가능

2) 상호 배제를 위한 동기화 : Bank account poblem

공유가 불가능한 자원의 동시 사용을 피하기 위한 동기화

-> 한 번에 하나의 프로세스만 접근해야 하는 자원에 동시 접근을 피하기 위한 동기화

 

ex) 현재 계좌에 잔액 : 10만원
1. 프로세스 A 
   (1) 계좌의 잔액을 읽어 들인다.
   (2) 읽어 들인 잔액에 2만원을 더한다.
   (3) 더한 값을 저장한다.
2. 프로세스 B
   (1) 계좌의 잔액을 읽어 들인다.
   (2) 읽어 들인 잔액에 5만원을 더한다.
   (3) 더한 값을 저장한다.

프로세스 A, 프로세스 B를 동시에 실행하면 17만원이 계좌에 남을까?

동기화가 제대로 이루어지지 않을 경우 위 그림과 같이 된다.

-> 프로세스 A와 B는 '잔액'이라고 하는 데이터를 동시에 사용하는데 프로세스 A가 끝나기도 전에 프로세스 B가 '잔액'이라고 하는 자원에 접근했기 때문에 위 그림과 같은 결과가 발생한다.

-> 이것은 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역인 임계 구역에 동시에 접근해 읽기/쓰기 작업이 수행되었기 때문!

 

2. 공유 자원과 임계 구역

(1) 공유 자원(Shared Resource)

  • 여러 프로세스 혹은 스레드가 공유하는 자원
  • 시스템 안에서 각 프로세스, 스레드가 함께 접근할 수 있는 모니터, 프린터, 메모리, 파일, 데이터 등의 자원이나 전역 변수
  • 공유 자원을 두 개 이상의 프로세스가 동시에 읽거나 쓰는 상황을 레이스 컨디션(Race Condition)이라고 한다.

(2) 임계 구역(Critical Section)

  • 공유 자원 중 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
  • 임계 구역에 진입하고자 한다면 진입한 프로세스 이외에는 대기해야 한다.

임계 구역에 동시에 접근해 읽기/쓰기 작업이 수행된다면 자원의 일관성이 깨지게 된다.

1) 운영체제가 임계구역 문제를 해결하는 세 가지 원칙

  1. 상호 배제(mutual exclusion) : 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 들어올 수 없다.
  2. 진행(progress) : 임계 구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
  3. 유한 대기(bounded waiting) : 한 프로세스가 임계 구역에 진입하고 싶다면 언젠가는 임계 구역에 들어올 수 있어야 한다.

 

2. 동기화 기법

(1) 뮤텍스 락

  • 뮤텍스는 프로세스나 스레드가 공유 자원을 acquire() ( =lock() )을 통해 잠금 설정하고 사용한 후에는 release() ( =unlock() )을 통해 잠금을 해제하는 객체이다. 다른 프로세스나 스레드는 잠긴 코드 영역에 접근할 수 없고 해제는 그와 반대이다. 또한 뮤텍스는 잠금 또는 잠금 해제라는 상태만을 가진다.
  • 상호 배제를 위한 동기화 도구(자물쇠 역할)

1) 형태

전역 변수 1개, 함수 2개로 구성되어 있다.

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

release() {
	lock = false; /* 임계 구역 작업이 끝났으니 잠금 해제 */
}

2) 과정

acquire(); // 자물쇠 잠겨 있는지 확인, 잠겨 있지 않다면 잠그고 들어가기
// 임계 구역 // 임계 구역에서의 작업 진행
release(); // 자물쇠 반환

 

 

3) 바쁜 대기(busy waiting)

acquire() 함수의 일부분으로 계속해서 임계 구역이 잠겨있는지를 반복적으로 확인하는 작업

while (lock == true) /* 만약 임계 구역이 잠겨 있다면 */
    	; /* 임계 구역이 잠겨 있는지를 반복적으로 확인 */

 

(2) 세마포어

  • 세마포어는 일반화된 뮤텍스
  • 공유 자원이 여러 개 있는 경우에도 적용 가능
  • 상호 배제를 위한 동기화 도구
  • 실행 순서 제어를 위한 동기화 도구

1) 개념

  • 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리기
  • 임계 구역 앞에서 가도 좋다는 신호를 받으면 임계 구역 진입

2) 형태

전역 변수 1개, 함수 2개로 구성되어 있다.

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

3) wait 함수

wait() {
	while ( S <= 0 ) /* 만일 임계 구역에 진입할 수 있는 프로세스 개수가 0개 이하라면 */
    ; /* 사용할 수 있는 자원이 있는지 반복적으로 확인하고 */
    S--; /* 임계 구역에 진입할 수 있는 프로세스 개수가 하나 이상이면 S를 1 감소시키고 임계 구역 진입 */
}

4) signal 함수

signal() {
	S++ /* 임계 구역에서의 작업을 마친 뒤 S를 1 증가시킨다 */
}

5) 예제

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

Step1. 프로세스 P1 wait 호출, S는 현재 2이므로 S를 1 감소시키고 임계 구역 진입

Step2. 프로세스 P2 wait 호출, S는 현재 21이므로 S를 1 감소시키고 임계 구역 진입

Step3. 프로세스 P3 wait 호출, S는 현재 0이므로 무한히 반복하며 S 확인

Step4. 프로세스 P1 임계 구역 작업 종료, signal() 호출. S를 1 증가

Step5. 프로세스 P3 S가 1이 됨을 확인. S는 현재 1이므로 S를 1 감소시키고 임계 구역 진입

6) Busy Waiting의 해결 방법

  • 문제점 : CPU 사이클 낭비
    • 마치 탈의실 문이 열렸는지/닫혔는지 반복적으로 확인하는 것과 같다
  • 사용할 수 있는 자원이 없을 경우 대기 상태로 만든다
    • 해당 프로세스의 PCB를 대기 큐에 삽입
  • 사용할 수 있는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태로 만든다.
    • 해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입
wait() {
	S--;
    if ( S < 0 ) {
    	add this process to Queue; /* 해당 프로세스 PCB를 대기 큐에 삽입한다 */
        sleep(); /* 대기 상태로 접어든다 */
    }
}

signal() {
	S++
    if ( S <= 0 ) {
    	remove a process p from Queue /* 대기 큐에 있는 프로세스 p를 제거한다 */
        wakeup(p) /* 프로세스 p를 대기 상태에서 준비 상태로 만든다 */
    }
}

7) Busy Waiting을 해결했을 때의 예시

Step1. 프로세스 P1 wait 호출, S를 1 감소시키면 S는 1이므로 임계 구역 진입

Step2. 프로세스 P2 wait 호출, S를 1 감소시키면 S는 0이므로 임계 구역 진입

Step3. 프로세스 P3 wait 호출, S를 1 감소시키면 S는 -1이므로 본인의 PCB를 대기 큐에 넣고 대기 상태로 전환

Step4. 프로세스 P1 임계 구역 작업 종료, signal() 호출. S를 1 증가하면 0이므로 대기 상태였던 P3를 대기 큐에서 꺼내 준비 큐로 옮겨줌

Step5. 깨어난 프로세스 P3 임계 구역 진입

Step6. 프로세스 P2 임계 구역 작업 종료, signal() 호출. S가 1 증가하면 1

Step7. 프로세스 P3 임계 구역 작업 종료, signal() 호출. S가 1 증가하면 2

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

  1. 세마포어의 변수 S를 0으로 두고
  2. 먼저 실행할 프로세스 뒤에 signal 함수
  3. 다음에 실행할 프로세스 앞에 wait 함수를 붙이면 된다.

9) 종류

  1. 바이너리 세마포어
    • 0과 1의 두 가지 값만 가질 수 있는 세마포어
    • 뮤택스는 잠금을 기반으로 상호 배제가 일어나는 '잠금 매커니즘'
    • 세마포어는 신호를 기반으로 상호 배제가 일어나는 '신호 매커니즘'
  2. 카운팅 세마포어
    • 여러 개의 값을 가질 수 있는 세마포어이며, 여러 자원에 대한 접근을 제어하는 데 사용

(3) 모니터

매번 임계구역 앞뒤로 wait(), signal()을 호출해야 하나?

실수가 발생한다면?

-> 그래서 모니터가 등장

-> 모니터는 둘 이상의 스레드나 프로세스가 공유 자원에 안전하게 접근할 수 있도록 공유 자원을 숨기고 해당 접근에 대해 인터페이스만 제공

-> 사용자(개발자)가 다루기에 편리한 도구

1) 상호 배제를 위한 동기화

  • 인터페이스를 위한 큐
  • 공유자원에 접근하고자 하는 프로세스를 (인터페이스를 위한) 큐에 삽입
  • 큐에 삽입된 순서대로 (한 번에 하나의 프로세스만) 공유 자원 이용

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

  • 조건 변수(condition variable) 이용
    • 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수
    • 조건변수.wait() : 대기 상태로 변경, 조건 변수에 대한 큐에 삽입
    • 조건변수.signal() : wait() 으로 대기 상태에 접어든 조건변수를 실행 상태로 변경

조건변수.wait()
조건변수.signal()

모니터 안에는 하나의 프로세스만이 존재할 수 있다.

  • wait()을 호출했던 프로세스는 signal()을 호출한 프로세스가 모니터를 떠난 뒤에 수행을 재개
  • signal()을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal()을 호출한 프로세스의 수행을 재개

즉,

  1. 특정 프로세스가 아직 실행될 조건이 되지 않았을 때는 wait를 통해 실행을 중단한다
  2. 특정 프로세스가 실행될 조건이 충족되었을 때는 signal을 통해 실행을 재개한다

3) 세마포어와 모니터의 차이점

모니터에서 상호 배제는 자동인 반면에, 세마포어에서는 상호 배제를 명시적으로 구현해야 하는 차이점이 있다.

  • 모니터가 세마포어보다 구현이 쉽다.

 

728x90
반응형