[혼공컴운] CH 12 프로세스 동기화

sookyoung.k·2024년 2월 4일
0

🤓 [혼공학습단] 

목록 보기
17/23
post-thumbnail

🔄 동기화란

✔️ 동기화의 의미

프로세스 동깋화 → 프로세스들 사이의 수행 시기를 맞추는 것

협력적으로 실행되는 프로세스들은 아무렇게나 마구 동시에 실행해서는 안 된다! 올바른 실행을 위해서는 동기화가 필수

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

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

동시에 실행되는 프로세스를 올바른 순서대로 실행하는 것

ex. Writer 프로세스와 Reader 프로세스가 동시에 실행 중일 때 Reader 프로세스에 'Book.txt 안에 값이 존재한다'는 특정 조건이 만족되어야만 실행을 이어갈 수 있게 조건을 준는 것

🌀 상호 배제를 위한 동기화

동시에 접근해서는 안 되는 자원에 동시에 접근하지 못하게 하는 것

상호 배제 - 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘

🛗 생산자와 소비자 문제

상호 배제를 위한 동기화에 관한 유명한 문제로 생산자와 소비자 문제가 있다!

생산자와 소비자 문제는 물건을 계속 생산하는 프로세스인 생산자물건을 계속해서 소비하는 프로세스인 소비자로 이루어져 있다.

➡️ 이 둘은 '총합'이라는 데이터를 공유하고 있다.

생산자

생산자 () {
	버퍼에 데이터 삽입
    '총합' 변수 1 증가
}

소비자

소비자 () {
	버퍼에서 데이터 빼내기
    '총합' 변수 1 감소
}

요런 상황에서 총합 변수를 10으로 초기화를 해준다.

언뜻 보기에 코드에 문제가 없어 보이지만 100,000번씩 동시에 실행을 해보면 예상치 못한 결과를 받을 수 있다.

우리는 총합 변수가 계속 10으로 머물러 있을 것으로 예상하지만 그렇지 않다!

초기 합계 : 10
producer, consumer 스레드 실행 이후 합계 : 63078
초기 합계 : 10
producer, consumer 스레드 실행 이후 합계 : -13750

이는 생산자 프로세스와 소비자 프로세스가 제대로 동기화 되지 않기 때문에 발생한다.

소비자가 생산자의 작업이 끝나기도 전에 총합을 수정, 생산자가 소비자의 작업이 끝나기도 전에 총합을 수정했기 때문!

🛗 공유 자원과 임계 구역

🌀 공유 자원

생산자와 소비자 문제에서 동시에 실행되는 프로세스들은 전역 변수인 '잔액', '총합'이라는 공동의 자원을 두고 작업을 했다. 이러한 자원을 공유 자원이라고 한다.

공유자원은 전역 변수가 될 수도 있고, 파일이 될 수도 있고, 입출력장치, 보조 기억장치가 될 수도 있다. 이 중에서는 두 개 이상의 프로세스를 동시에 실행하면 문제가 발생하는 자원이 있다.

⚠️ 임계 구역

동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역

두 개 이상의 프로세스가 임계 구역에 진입하고자 하면 둘 중 하나는 대기를 해야 한다!
→ 먼저 진입한 프로세스의 작업이 마무리되면 그제서야 비로소 기다렸던 프로세스가 임계 구역에 진입한다

하지만 잘못된 실행으로 인해 여러 프로세스가 동시 다발적으로 임계 구역의 코드를 실행하여 문제가 발생하는 경우가 있는데, 이를 레이스 컨디션이라고 한다.
➡️ 데이터의 일관성이 깨지는 문제가 발생!

🔆 임계 구역의 문제를 해결할 세 가지 원칙

운영 체제는 임계 구역의 문제를 아래 세 가지 원칙 하에 해결한다.

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

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

  • 유한 대기
    😀 한 프로세스가 임계 구역에 진입하고 싶다면 그 프로세스는 언젠가는 임계 구역에 들어올 수 있어야 한다

♻️ 동기화 기법

✳️ 뮤텍스 락

동시에 접근해서는 안 되는 자원에 동시에 접근하지 않도록 만드는 도구, 상호 배제를 위한 동기화 도구

(비유하자면 한 번에 한 명씩만 사용할 수 있는 탈의실의 자물쇠같은 역할로 탈의실은 임계 구역, 손님은 프로세스에 해당)

뮤텍스 락은 하나의 전역 변수와 두 개의 함수로 구현이 가능하다

  • 프로세스들이 공유하는 전역 변수 lock
  • 임계 구역을 잠그는 역할인 acquire() 함수
  • 임계 구역의 잠금을 해재ㅔ하는 역할인 release() 함수

✔️ acquire 함수

프로세스가 임계 구역에 진입하기 전에 호출하는 함수

임계 구역이 잠겨 있다면 임계 구역이 열릴 때까지 (lock이 false가 될 때까지) 임계 구역을 반복적으로 확인, 임계 구역이 열려 있다면 임계 구역을 잠그는 (lock을 true로 바꾸는) 함수이다.

✔️ release 함수

임계 구역에서의 작업이 끝나고 호출하는 함수

현재 잠긴 임계 구역을 열어주는 (lock을 false로 바꾸는) 함수

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

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

acquire 함수와 release 함수를 임계 구역 전후로 호출함으로써 하나의 프로세스만 임계 구역에 진입할 수 있다.

acuire();			// 자물쇠 잠겨 있는지 확인, 잠겨 있지 않다면 잠그고 들어가기 
// 임계 구역		 // 임계 구역에서의 작업 진행
release();			// 자물쇠 반환  
  • 락을 획득할 수 없다면(임계구역 진입 불가) 무작정 기다리고
  • 락을 획득할 수 있다면(임계구역 진입 가능) 임계 구역을 잠근 뒤 임계 구역에서의 작업을 진행하고
  • 임계 구역에서 빠져나올 땐 다시 임계 구역의 잠금을 해제함으로써

임계 구역을 보호할 수 있다.

* 바쁜 대기
쉴 새 없이 반복하면 임계 구역의 상태를 확인하는 것

✳️ 세마포

동기화는 상호 배제를 위한 동기화가 있고, 실행 순서 제어를 위한 동기화가 있다.

🔄 세마포를 이용한 상호 배제를 위한 동기화 기법

세마포는 뮤텍스 락과 비슷하지만, 조금 더 일반화 된 방식의 동기화 도구로 공유 자원이 여러 개 있는 상황에서도 적용이 가능한 동기화 도구이다.

* 뮤텍스 락은 하나의 공유 자원에 접근하는 프로세스를 상정한 방식

→ 공유 자원이 여러 개 있을 경우 여러 개의 프로세스가 각각 공유 자원에 접근이 가능해야 한다!

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

세마포도 임계 구역 진입 전후로 wait()signal()을 호출한다

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

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

세 개의 프로세스 P1, P2, P3가 두 개의 공유 자원에 P1, P2, P3 순서로 접근한다고 가정할 시, 아래와 같은 순서로 실행된다
* 공유 자원은 두 개 있기 때문에 변수 S는 2

P1P2P3
wait()wait()wait()
//임계 구역//임계 구역//임계 구역
signal()signal()signal()
  • 각각 wait()를 호출하지만 P1과 P2는 S를 감소시키고 임계 구역에 진입하는 반명 P3의 순서에 이르러서는 S가 현재 0이므로 무한히 반복하며 S를 확인한다
  • 프로세스 P1 임계 구역 작업이 종료하여 signal() 호출한 후 S가 1 증가한다
  • 프로세스 P3이 S가 1이 됨을 확인한 후 S를 1 감소시키고 임계 구역에 진입한다

뮤텍스 락과 마찬가지로 바쁜 대기가 발생한다!
☹️ 이는 CPU 주기를 낭비한다는 점에서 손해이다. 그래서 실제로 세마포는 다른 더 좋은 방법을 사용한다.

  1. wait()함수는 만일 사용할 수 있는 자원이 없을 경우 해당 프로세스 상태를 대기 상태로 만들고, 그 프로세스의 PCB를 세마포를 위한 대기 큐에 집어넣는다.
  2. 다른 프로세스가 임계 구역에서의 작업이 끝나고 signal() 함수를 호출하면 대기 중인 프로세스를 대기 큐에서 제거하고 프로세스 상태를 준비 상태로 변경한 뒤 준비 큐로 옮겨 준다.
wait() {
	S--;
  	if (S < 0) {
    	add this process to Queue;
      	sleep();
    }
}

signal() {
	S++;
  	if (S <= 0) {
    	remove a process p from Queue;
      	wakeup(p);
    }
}

🔄 세마포를 이용해 프로세스의 순서를 제어하는 방법

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

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

✳️ 모니터

🔄 모티터를 이용한 상호 배제를 위한 동기화 기법

세마포는 훌륭한 프로세스 동기화 도구이지만 매번 임계 구역의 앞뒤로 일일이 wait()와 signal() 함수를 명시하는 것은 번거로운 일이다.

그래서 등장한 동기화 도구가 바로 모니터로 사용자가 사용하기에 훨씬 더 편리한 도구이다!

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

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

* 모니터에 진입하기 위해 삽입되는 큐(상호 배제를 위한 큐)와 wait()가 호출되어 실행이 중단된 프로세스들이 삽입되는 큐(조건 변수에 대한 큐()는 다른 것이다!!
➡️ 모니터에 한 번에 하나의 프로세스만 진입하도록 하기 위해 만들어진 큐 vs 모니터에 이미 진입한 프로세스의 실행 조건이 만족될 때까지 잠시 실행이 중단되어 기다리기 위해 만들어진 큐

➡️ 공유 자원을 다루는 인터페이스에 접근하기 위한 큐(모니터에 진입하기 위한 큐)를 만들고, 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 상호 배제를 위한 동기화를 제공한다.

🔄 모니터를 이용해 프로세스의 순서를 제어하는 방법

특정 조건을 바탕으로 프로세스를 실행하고 일시 중단하기 위해 모니터는 조건 변수를 사용한다.
→ 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수이다.

조건 변수로는 wait()와 signal() 연산을 수행할 수 있다.

  • wait(): 호출한 프로세스의 상태를 대기 상태로 전환하고 일시적으로 저건 변수에 대한 대기 큐에 삽입하는 연산
    → 일시 중지된 프로세스는 다른 프로세스의 signal() 연산을 통해 실행이 제개될 수 있다
  • signal(): wait()를 호출하여 큐에 삽입된 프로세스의 실행을 재개하는 연산

모니터는 조건 변수를 이용하여 아래와 같은 프로세스 실행 순서 제어를 위한 동기화를 제공한다.

  • 특정 프로세스가 아직 실행될 조건이 되지 않았을 때에는 wait()를 통해 실행을 중단한다
  • 특정 프로세스가 실행될 조건이 충족되었을 때에는 signal()을 통해 실행을 재개한다
profile
영차영차 😎

0개의 댓글