6. Process Synchronization 3, 4

운영체제 – 이화여대 KOWC 공개강의

 

Synchronization과 관련된 고전적인 문제 3가지

1. Bounded-Buffer Problem
프로세스의 두 종류가 있다. 프로듀서와 컨슈머. 하나씩만 있는 것이 아니라 각각 여러개의 프로세스가 있다. 위 그림에서 주황색 원은 데이터가 들어있는 버퍼를 나타낸다. 이는 생산자 프로세스가 데이터를 만들어서 집어넣어놓은 상태를 말한다. 구멍이 뚫려있는 버퍼는 애초부터 비어있던 상태이던지 아니면 생산자가 데이터를 집어 넣었는데 컨슈머가 데이터를 빼가서 비었던지의 두 경우가 있을 수 있다.
동기화와 관련하여 어떤 문제가 발생할 수 있나? 한가지 문제는 공유 버퍼이기 때문에 생산자 둘이 동시에 비어있는 하나의 버퍼에 데이터를 집어넣을 수 있다. 그래서 생산자는 이 공유버퍼에 데이터를 넣을 때 이 버퍼에 락을 걸어서 다른 프로세스의 접근을 막은 다음에 비어있는 버퍼에 데이터를 집어넣는 작업을 하게 된다. 이 작업이 끝나면 락을 풀어서 다른 생산자나 소비자가 공유버퍼를 접근할 수 있게 한다. 소비자 프로세스도 마찬가지로 소비자 프로세스들이 동시에 하나의 데이터를 꺼내가려고 할 수 있다.

또 다른 문제는 버퍼가 유한하기 때문에(bounded buffer) 발생하는 문제이다. 만약 버퍼의 데이터가 가득 찬 상태에서 생산자가 또 도착해서 데이터를 만들어서 집어넣으려는 상황이 올 수도 있다. 생산자 입장에서는 생산 할 수 있는 자원이 없는 상태로 볼 수 있다. 생산자는 소비자가 버퍼에서 데이터를 꺼내가야만 데이터를 만들어서 집어 넣을 수 있게 된다. 생산자 입장에서는 비어있는 버퍼의 개수가 카운팅을 해놔야 할 자원이 된다. 생산자 프로세스는 비어있는 버퍼가 나올 때까지 기다려야 한다.
소비자 입장에서는 만약 모든 버퍼에 데이터가 없는 상태이면 더 이상 꺼내갈 데이터가 없는 상태가 된다. 소비자 입장에서의 자원은 데이터가 들어있는 버퍼이다. 데이터가 들어있는 버퍼의 갯수가 0이 되면 소비자 프로세스는 생산자 프로세스가 데이터를 집어 넣을 때까지 기다려야 한다.

그래서 생산자 소비자 문제에서는 세마포가 해야될 업무가 크게 두 가지가 있다. 하나의 프로세스가 작업을 할 때 락을 걸어놓고 작업이 끝나면 락을 풀어주는 역할과 버퍼가 가득차거나 비었을때 참고 할 수 있도록 생산자, 소비자 프로세스의 가용자원의 갯수를 세는 카운팅 세마포어의 역할이다.

프로세스의 두 종류가 있다. 읽는 프로세스와 쓰는 프로세스. 공유데이터를 DB라고 명명한다.

 

철학자의 일. 생각하고 밥먹고. 철학자마다 생각하고 밥먹고 하는 주기가 다 다르다. 밥을 먹으려면 양쪽의 젓가락 두 개를 다 잡아야 한다. 젓가락=공유 자원.

 

세마포의 문제점. 프로그래머가 실수를 하면 동기화가 깨어져서 프로그램에 치명적인 영향을 받는다. 반면에 monitor라는 것은 프로그래밍 언어 차원에서 공유데이터를 접근하는 것과 관련된 것을 모니터가 자동으로 해결해주도록 함으로서 프로그래머의 부담을 확 줄여준다.

공유데이터를 접근할 때는 공유데이터와 이를 접근하는 코드를 모니터 안에다 정의해서 만약에 프로세스가 공유데이터를 접근하려고 하면 모니터 안에 정의된 코드를 이용해서만 공유데이터에 접근할 수 있게 만들어 놓는다. 그리고 공유데이터를 프로세스들이 동시에 접근할 수 없도록 애초에 막아놓는 것이다. 액티브한 프로세스 하나만이 모니터 안에 있는 코드를 실행할 수 있게 모니터 자체가 제어를 해주는 방식이다. 그래서 프로그래머는 프로세스들이 어떤 공유데이터에 동시에 접근하려는 것을 제어하기 위해 락을 걸고 푸는 코드를 작성할 필요가 없어진다. 모니터가 알아서 제어를 해준다.

예를 들어 어떤 프로세스가 모니터 안에 들어와서 공유데이터를 접근하고 있는 코드를 실행하고 있다면 접근 도중 CPU를 빼앗겨서 또다른 프로세스가 모니터를 접근하려는 코드를 수행하려고 하면 이미 CPU를 빼앗긴 프로세스가 모니터 접근 코드를 실행 중이었기 때문에 여전히 이 프로세스는 모니터 안에 액티브한 상태로 남아있다. 그래서 다른 프로세스가 모니터 안에 있는 코드를 실행하지 못하고 모니터 밖의 entry 큐에 줄서서 기다리게 된다. 줄 서 있는 프로세스들은 모니터 내부에 액티브 프로세스 수가 0이 될때 모니터 내부로 들어와서 코드를 수행할 수 있다.

모니터에서는 원칙적으로 락을 걸고 풀고 하는게 필요가 없다. 모니터가 알아서 제어를 해준다. 프로그래밍 언어마다 모니터를 어떻게 지원할지는 조금씩 다르다.

모니터에서는 condition variable을 둘 수 있다. 모니터 안에서 어떤 코드를 실행하다가 뭔가 충족이 되지 않아서 오래 걸려야 되는 경우이면 그 프로세스를 잠들게 한다. 어떤 조건이 충족이 되지 않아 잠들었는지의 경우에 따라 그 조건에 해당하는 것을 condition 변수로 둘 수 있다.

이런 condition 변수는 세마포에서 처럼 어떤 값을 가지는 변수가 아니라 어떤 프로세스를 잠들게하고 줄 세우게 하기 위한 변수이다. 갯수를 카운트하거나 값을 가지거나 하는 의미를 가지고 있지는 않다. condition 변수에 대해서는 두가지 연산이 이루어질 수 있다. 하나는 wait()이고 다른 하나는 signal()이다. wait()는 어떤 프로세스를 잠들게 한다. x.wait()를 호출하면 해당 프로세스는 condition x 변수에 가서 줄 서 있게 된다. 프로세스가 x라는 조건을 만족하지 못해 잠들게 된다. x.signal()은 다른 프로세스가 x를 다쓰고 빠져나가서 잠들어있는 프로세스가 있으면 그 중에 하나를 깨워줘라는 연산이다.

댓글 남기기

Close Menu