운영체제 : 프로세스 동기화

mmmYoung·2023년 5월 5일
0

운영체제

목록 보기
5/10
post-custom-banner

프로세스 동기화

동시다발적으로 실행되는 프로세스(스레드)들은 서로 협력하며 영향을 주고 받는다. 이때 자원의 일관성을 보장해야 한다. 즉 프로세스의 동기화를 고려해야 함!

즉 동기화란, 프로세스들의 수행 시기를 맞추는 것이다.(스레드도 동기화 대상) 동기화에는 두 가지 목적이 있다.

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

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

ex) reader writer problem

Reader와 Writer 프로세스에는 실행의 순서가 존재하기 때문에, 아무렇게나 실행되면 안된다.

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

상호 배제를 위한 동기화

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

ex) Bank account problem

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

아니다!

동기화를 거치지 않으면 위와 같이 실행되어 15만원이 남는다.
프로세스 A가 끝나기 전에 B가 실행되었기 때문.

만약 동기화를 거치게 되면 아래와 같이 정상적인 결과가 나온다.

ex) Producer & Consumer Problem 생산자 소비자 문제
물건을 계속해서 생산하는 생산자와, 계속해서 소비하는 소비자가 있다. 총합 변수는 서로 공유한다.

만약 생산자를 100,000번 소비자를 100,000번 실행하면 총합은 어떻게 될까?

당연히 0이 남아야 하지 않을까?

실행결과는 다르다.
때로는 0과 다른 값이 되거나, 오류가 발생하기도 한다.

그 이유는
동시에 접근해서는 안되는 자원(총합)에 동시에 접근해서 발생한 문제. 즉 동기화가 되지 않았기 때문!

동시에 접근하면 안되는 자원은 뭘까?

공유 자원과 임계 구역

공유 자원은 여러 프로세스나 스레드가 공유하는 자원을 말한다. 전역 변수, 파일, 입출력장치,보조기억장치 등을 의미한다.

임계 구역은 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드영역을 말한다. 위의 예시에서는 총합 변수나, 잔액 변수를 말한다.

이러한 임계구역에 진입하고자 한다면, 한 번에 하나의 프로세스만이 들어가야하기 때문에 대기해야한다.

레이스 컨디션(race condition)
: 임계구역에 동시에 접근하여 자원의 일관성이 깨지는 현상(문제)를 말한다.

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

운영체제가 임계구역 문제를 해결하기 위한 세 가지 원칙이 있다.

1. 상호배제

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

2. 진행

임계 구역에 어떤 프로세스도 진입하지 않았다면, 진입하려고 하는 프로세스는 들어갈 수 있어야 한다.

3. 유한대기

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

프로세스 동기화의 기법

뮤텍스 락

상호 배제를 위한 동기화 도구. 자물쇠 역할을 함.
자물쇠 역할의 전역 변수(lock) 하나와 임계 구역을 잠그고(acquire) 해제(release)하는 두 함수로 간단히 구현할 수 있다.

acquire() {
	while(lock == true) //만약 임계 구역이 잠겨 있다면
    	;				//임계 구역이 계속 잠겨 있는 지 반복적으로 확인 
        				//(계속하여 확인하는 것을 busy waiting, 바쁜 대기라고 함)
    lock = true;		//잠겨 있지 않다면 잠금 실행
}

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

뮤텍스 락은 아래처럼 이용할 수 있다.

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

(카운팅) 세마포

공유 자원(탈의실)이 여러개 있는 경우에도 사용할 수 있는 좀 더 일반화된 동기화 도구이다.

임계 구역 앞에서 멈춤 신호를 받으면 기다리고, 통과 신호를 받으면 진입한다.

임계 구역에 진입할 수 있는 프로세스의 개수(사용 가능한 공유 자원의 개수)를 나타내는 전역 변수 S, 들어갈지 기다려야 할지를 알려주는 wait함수, 임계 구역 앞에서 기다리는 프로세스에게 통과 신호를 주는 signal함수로 구현할 수 있다.

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


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

아래와 같이 이용할 수 있다.

wait()
// 임계 구역
signal()

Busy waiting을 해결하기

위의 모든 while문에서 모두 Busy waiting을 사용했는데, 이는 CPU의 사이클을 낭비하는 행위이다. 좀 더 효율적인 방법이 있다.

  1. 사용할 수 있는 자원이 없을 경우 대기 상태로 만든다. (해당 프로세스의 PCB를 대기 큐에 삽입)
  2. 사용할 수 있는 자원이 생기면, 대기 큐의 프로세스를 준비 상태로 만든다. (해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입)

busy waiting을 사용한 예시와, 해결한 예시는 아래와 같다.

세마포를 활용한 실행 순서 동기화

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

모니터

매번 임계구역 앞 뒤로 wait(), signal()을 호출해야하나?
이런 번거로움을 해결하기 위한 방법!
사용자가 다루기 편한, 상호배제와 실행 순서를 위한 두 경우 모두를 고려하는 동기화 도구이다.

상호 배제를 위한 동기화

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

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

조건 변수(conditional variable) 이용

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

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

  1. 특정 프로세스가 아직 실행될 조건을 미충족 -> wait를 통해 실행을 중단
  2. 특정 프로세스가 실행될 조건을 충족 -> signal을 통해 실행 재게
출처 한빛미디어 혼자 공부하는 컴퓨터 구조+운영체제
profile
안냐세여
post-custom-banner

0개의 댓글