본문 바로가기
Computer Science/컴퓨터 구조

[컴퓨터 구조] Chapter 12 프로세스 동기화

by BrickSky 2023. 12. 30.

동기화란

동시다발적으로 실행되는 프로세스들은 공동의 목적을 올바르게 수행하기 위해 서로 협력한다. 이렇게 협력해서 실행하는 프로세스들은 실행 순서와 자원의 일관성을 보장해야 하기 때문에 반드시 동기화되어야 한다.
 

1) 동기화의 의미

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

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

 
이처럼 동기화에는 실행 순서를 위한 동기화가 있고, 상호 배제를 위한 동기화가 있다.
실행 순서를 위한 동기화는 쉽게 말해 올바른 순서대로 프로세스를 실행할 수 있도록 하는 것이다. 상호 배제는 공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘이다.
 
 

2) 생산자와 소비자 문제

생산자와 소비자 문제는 물건을 계속해서 생산하는 프로세스인 생산자와 물건을 계속해서 소비하는 프로세스인 소비자로 이루어져있다. 생산자와 소비자는 총합이라는 데이터를 공유한다. 생산자는 버퍼에 물건을 넣고 총합에 해당하는 변수 1을 증가시키고, 소비자는 버퍼에 물건을 꺼낸 후 총합에 해당하는 변수를 1 감소시킨다.
 
생산자

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

 
소비자

소비자() {
		버퍼에 데이터 삽입
		'총합' 변수 1 감소
}

 
 

3) 공유 자원과 임계 구역

생산자 소비자 문제에서 동시에 실행되는 프로세스는 전역 변수인 ‘잔액’과 ‘총합’이라는 공동의 자원을 두고 작업했다. 이러한 자원을 공유자원이라고 한다. 공유 자원은 전역 변수가 될 수도 있고, 파일이 될 수도 있고, 파일이 될 수도 있고, 보조기억장치가 될 수도 있다.
 
동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역을 임계구역이라고 한다. 두 개 이상의 프로세스가 임계구역에 진입하고자하면 둘 중 하나는 대기해야 한다. 임계 구역에 먼저 진입한 프로세스의 작업이 마무리되면 그제야 비로소 기다렸던 프로세스가 임계구역에 진입한다.

 
동시 다발적으로 임계 구역의 코드를 실행하여 문제가 발생하는 경우가 있는데, 이를 레이스 컨디션이라고 한다.
 
운영체제는 이러한 임계 구역 문제를 아래 세 가지 원칙 하에 해결한다.

  • 상호 배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 임계 구역에 들어올 수 없다.
  • 진행: 임계 구역에 어떤 프로세스도 진입하지 않았다면 임계 구역에 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
  • 유한 대기: 한 프로세스가 임계 구역에 진입하고 싶다면 그 프로세스는 언젠가 임계 구역에 들어올 수 있어야 한다. (임계 구역에 들어오기 위해 무작정 대기해서는 안된다)

 
 

동기화 기법

1) 뮤텍스 락

임계 구역 문제와 이를 해결하기 위한 동기화를 옷 가게에서 탈의실을 이용하는 것에 비유할 수 있다.
탈의실에는 손님 한명만 들어올 수 있기에 손님은 프로세스, 탈의실은 임계 구역이라고 할 수 있다.
 
밖에서 탈의실에 사람이 있는지 없는지 알 수 없는 상황일 때, 탈의실을 열어보고 자물쇠가 걸려있다면 탈의실 안에 사람이 있을 테고 걸려있지 않다면 탈의실을 이용하면 될 것이다.
 
이 자물쇠 기능을 코드로 구현한 것이 뮤텍스 락이다. 뮤텍스 락은 동시에 접근해서는 안 되는 자원에 동시에 접근하지 않도록 만드는 도구, 다시 말해 상호 배제를 위한 동기화 도구이다. 뮤텍스 락은 하나의 전역변수와 두 개의 함수로 구현할 수 있다.

  • 자물쇠 역할: 프로세스들이 공유하는 전역변수 lock
  • 임계 구역을 잠그는 역할: acquire 함수
  • 임계 구역의 잠금을 해제하는 역할: release 함수

acquire 함수는 프로세스가 임계구역에 진입하기 전에 호출하는 함수이다. 만일 임계 구역이 잠겨있다면 임계 구역이 열릴 때까지(lock이 false가 될 때까지) 임계 구역을 반복적으로 확인하고, 임계 구역이 열려있다면 임계구역을 잠그는(lock을 true로 바꾸는) 함수이다.
 
release 함수는 임계 구역에서의 작업이 끝나고 호출하는 함수이다. 현재 잠긴 임계 구역을 열어주는 (lock을 false로 바꾸는) 함수이다.

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

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

 
acquire와 release 함수를 아래와 같이 임계 구역 전후로 호출해서 하나의 프로세스만이 임계 구역에 진입할 수 있다. 예시도 아래에서 볼 수 있다.

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

이렇게 되면,
락을 획득할 수 없다면 무작정 기다리고, 락을 획득할 수 있다면 임계 구역을 잠근 뒤 임계 구역에서 작업을 진행하고, 임계 구역에서 빠져나올 땐 임계 구역의 잠금을 해제함으로써 임계 구역을 보호할 수 있다.

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

마치 탈의실 문이 잠겨있는지 쉴 새 없이 반복하며 확인하는 것인데, 이를 바쁜 대기 상태라고 한다.
 

2) 세마포

세마포는 뮤텍스 락과 비슷하지만 좀 더 일반화된 방식의 동기화 도구이다. 뮤텍스 락은 하나의 공유 자원에 접근하는 프로세스를 상정하는 방식이다. 탈의실이 하나인 경우를 가정하고 만든 동기화 도구이다. 하지만 탈의실이 여러 개 있는 상황처럼 공유 자원이 여러 개 있을 경우 여러 개의 프로세스가 각각 공유 자원에 접근 가능해야 한다. 이처럼 세마포는 공유 자원이 여러개 있는 상황에서도 적용이 가능한 동기화 도구이다.
 
프로세스는 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리고, 가도 좋다는 신호를 받으면 그제야 임계 구역에 들어간다. 세마포도 뮤텍스 락과 마찬가지로 하나의 변수와 두 개의 함수로 구현할 수 있다.

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