[운영체제] 동기화와 동기화 기법

Narcoker·2023년 6월 15일
0

운영체제

목록 보기
8/13

동기화

여러 프로세스나 스레드가 공유자원에 접근하거나
특정 조건을 만족시키기 위해서 서로 기다리는 과정을 의미한다.

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

수행 시기를 맞춘다는 것은 크게 두가지를 말한다.

  • 실행 순서 제어 프로세스를 올바른 순서대로 실행한다.
  • 상호 배제 공유 자원에는 반드시 단 하나의 프로세스만 접근하게 한다.

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

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

다음 두 프로세스가 동시에 실행 중이라고 가정하자.

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

이 두 프로세스는 순서가 매우 중요하다.
반드시 파일에 값을 저장하고 저장된 값을 읽어야한다.

이렇게 동시에 실행되는 프로세스를 올바른 순서대로 실행하는 것을
실행 순서를 제어하기 위한 동기화 이다.

상호 배제를 위한 동기화

공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘이다.

은행 계좌에 대한 두 개의 별도의 트랜잭션이 있다고 가정하자.
각각은 같은 계좌에서 돈을 인출하려고 하는데
만약 두 트랜잭션이 동시에 실행되면
인출이 2번 되는 등 계좌 잔액이 잘못 계산될 수 있다.

이러한 현상을 막기 위해 동기화가 필요하며
이런 메커니즘을 상호 배제를 위한 동기화라고 한다.

생산자-소비자 문제

생산자는 데이터를 생성하고 버퍼에 추가하며,
소비자는 버퍼에서 데이터를 제거하고 사용한다.

이 두 과정은 동시에 발생할 수 있기 때문에 상호 배제 동기화가 필요하다.

또한 생산자버퍼 오버플로우를 방지하기 위해 버퍼가 꽉차면 데이터를 추가하지 못하도록 해야한다.
소비자버퍼 언더플로우를 방지하기위해 버퍼가 비어 있으면 데이터를 소비하지 못하도록 해야한다.

공유 자원과 임계구역

공유 자원은 여러 프로세스들이 같이 사용하는 자원을 말한다.

예시로는 전역 변수, 파일, 입출력장치, 보조기억장치 등이 있다.

임계 구역동시에 접근하면 "문제가 생기는 공유 자원"에 접근하는 코드 영역 말한다.

임계 구역에는 반드시 하나의 프로세스만 접근해야 한다.
만약 다른 프로세스가 임계 구역을 점거하고 있다면 대기해야한다.

Race Condition

잘못된 실행으로 인해
여려 프로세스가 동시 다발적으로 임계 구역의 코드를 실행하여
문제를 발생하는 경우를 말한다.

이 경우 데이터의 일관성을 해치게 된다.

개발자가 작성하는 코드는 고급 언어이다.
하지만 컴퓨터는 고급언어를 저급언어로 변환하여 실행한다.

한 줄의 고급언어를 저급언어로 변환하면 여러 줄이 될 수 있다.
그 여러줄에 저급언어가 실행되는 과정에서 문맥교환이 일어나면
자원의 일관성이 깨질 수 있다.

예를 들어 x = x + 1 을 저급언어로 변경하면 다음과 같이 될 수 있다.

메모리에서 x의 값을 가져온다
그 값을 1만큼 증가시킨다
증가된 값을 다시 x 에 저장한다

동일한 스레드가 동시에 x = x + 1 을 수행한다고 가정하자
위 세단계가 다 완료되기전에 문맥교환이 발생하고 다른 스레드가 동일한 작업을 수행하기 시작하면
원래 기대한 값보다 최종 값이 1 적게 증가될 수도 있다.

두 스레드가 거의 동시에 x의 원래 값을 읽고 그 값에 1을 더하여
동일한 값을 다시 x에 저장할 수 있기 때문이다.

동기화를 적용하기 위한 세가지 원칙

상호배제 (mutual exclusion)

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

진행 (progress)

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

유한 대기 (bounded waiting)

임계 구역에 들어오기 위해서 무한정 대기해서는 안된다.

동기화 기법

뮤텍스 락

상호 배제를 위한 동기화 기법이다.

임계 구역에 진입하는 프로세스는
다른 프로세스가 진입하지 못하도록 공유자원에 Lock을 건다.

다른 프로세스는 공유자원이 Lock 상태라면 기다리고
그렇지 않다면 임계 구역에 진입한다.

전역 변수 Lock 자물쇠의 상태를 저장하는 변수
acquire 함수 자물쇠를 잠그는 함수
release 함수 자물쇠를 푸는 함수

acquire 함수

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

만약 임계 구역이 잠겨있다면
임계 구역이 열릴 때까지(Lock이 false) 가 될때까지 반복적으로 확인하고 ,

임계 구역이 열려있다면 임계 구역을 잠그는(Lock을 true로 바꾸는) 함수이다.

acquire() {
	while(Lock == true){
    	// 임게 구역이 잠겨 있는지 확인, 이러한 대기 방식을 busy wait 라고한다.
    }

    Lock = true;
	}

release 함수

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

잠긴 임계 구역을 열어주는(Lock을 false로 바꾸는) 함수이다.

release() {
	Lock = false;
}

카운팅 세마포

뮤텍스같은 공유자원의 개수가 1개 있는 경우를 가정하고 만든 동기화 도구이다.

카운팅 세마포의 경우 같은 공유 자원의 개수가 여러 개 있는 경우를 가정하고 만든 동기화 도구이다.

전역 변수 S 임계 구역에 진힘할 수 잇는 프로세스의 개수(사용가능한 공유자원의 개수)의 역할
wait 함수 임계 구역에 갈 수 있는지 기다려야하는지 알려주는 함수
signal 함수 임계 구역 앞에서 기다리는 프로세스에게 들어가도 된다는 신호를 주는 함수

wait 함수

임계 구역에 갈 수 있는지 기다려야하는지 알려주는 함수이다.

wait() {
	while(S <= 0){ // 사용할 자원이 없으면 0 이다. 
    	// 사용할 자원이 있는지 반복적으로 확인
    }
    S--;
}    

Signal 함수

임계 구역 앞에서 기다리는 프로세스에게 들어가도 된다는 신호를 주는 함수 이다.

signal() {
	S++;
}

세마포의 순서제어 기법

작성 중

문제점

뮤텍스 락과 마찬가지로 사용할 수 없는 자원이 없으면 반복적으로 확인한다.

이러한 작업은 CPU 를 낭비한다.

그러나 카운팅 세마포의 wait 함수에서는 사용할 수 있는 자원이 없는 경우
해당 프로세스를 waiting(또는 Blocking) 상태로 만들고
프로세스의 PCB세마포를 위한 대기 큐에 넣는다.

그리고 다른 프로세스가 임계 구역에서 작업이 끝나고 signal 함수를 호출하면
대기 큐에 있던 프로세스ready 상태로 만들고 ready queue에 넣는다.

이진 세마포

카운팅 세마포와 비슷하지만
전역 변수 S 값을 01만 가지는 세마포
S 가 0이면 잠겨있는 것이고, 1이면 잠금이 해제된 것

카운팅 세마포와 마찬가지로 wait() 과 signal() 을 사용하여
신호 전달 메커니즘을 사용해서 잠금을 구현함

현재 스레드보다 우선순위가 높은 쓰레드가 잠금을 해제하고 잠글 수 있다. 선점 가능
이러한 이유로 공유자원에 대한 소유권이 없고
잠금/해제 권한이 여러 프로세스에게 있기 때문에 뮤텍스 락 보다 속도가 빠르다.

이진 세마포와 뮤텍스의 차이 정리

모니터

세마포에서 임계 구역 앞뒤로 wait과 signal 함수를 매번 명시하는 것은 번거롭다.

또한 순서 변경 혹은 앞뒤로 같은 함수를 명시하는 예기치 못한 실수가 발생할 수 있다.

이러한 불편함을 해소하고자 나온 메커니즘이 모니터이다.

모니터는 공유 자원공유 자원에 접근하기 위한 인터페이스를 묶어 관리한다.

프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근하도록 한다.
이를 위해서 모니터를 통해 공유 자원에 접근하고자하는 프로세스를 큐에 삽입하고
삽입한 순서대로 하나씩 공유자원을 이용하도록 한다.

즉 모니터 안에 항상 하나의 프로세스만 들어오게 되어
상호 베제를 위한 동기화를 제공한다.

모니터는 실행 순서 제를 위한 동기화도 제공한다.
특정 조건을 바탕으로 프로세스를 실행하고 일시 중단하기 위해 조건 변수를 사용한다.

조건 변수란 프로세스나 실행 순서를 제어하기위해 사용하는 특별한 변수이다.
이 조건 변수에는 wait() 에 의해서 waiting 상태가 된 프로세스를 저장하는 큐가 할당되어있다.

wait() 연산으로 큐에 들어간 프로세스
signal() 에 의해서 모니터의 인터페이스로 이동할 수 있다.

따라서 signal() 에 의해서 모니터 인터페이스로 이동한 프로세스는
signal()을 호출한 프로세스가 모니터를 떠난뒤에 실행되거나

signal()을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal()을 호출한 프로세스를 재개한다.`

profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글