이전 글에서 프로세스 동기화가 무엇이고 왜 필요한가?에 대한 글을 작성하였다.
이번에는 프레스 동기화를 이루어내기 위해 어떤 기법을 사용하는지
프로세스 동기화 기법에 대해 이야기 해보겠다.
프로세스 동기화 기법은 프로세스 동기화를 위한 도구를 기준으로 나뉘게 된다.
대표적인 도구 3가지 뮤텍스 락, 세마포, 모니터가 존재한다.
그리고 동기화 기법을 설명하기 위해서 먼저 간단히 알아야 할 개념들이 존재하는데 이것들 부터 먼저 설명하고 그 후에 프로세스 동기화 도구들에 대해 설명하겠다.
공유자원은 말 그대로 프로세스들이 공동으로 사용하는 자원으로, 전역 변수가 될 수도 있고, 파일이 될 수도 있고, 입출력장치, 보조기억장치가 될 수도 있다.
공유 자원에 접근하는 코드 중 동시에 실행하면 문제가 발생하는 코드 영역을 의미한다. 임계 구역에 진입한 프로세스가 있다면 다른 프로세스는 임계 구역밖에서 기다려야 한다.
이제 간단한 사전 지식을 공부했으니 프로세스 동기화 기법에 사용되는 도구들에 대해 알아보도록 하겠다.
프로세스 동기화 도구에는 크게 3가지 뮤텍스 락, 세마포, 모니터가 있다.
바닷가에 놀러 갔는데 갑자기 신호가 와 화장실에 간다고 치자.
그런데 이미 화장실은 누가 사용중인 걸 깨달았다.
화장실에 누가 있는걸 어떻게 알았을까? 알고보니 화장실 문에 사용중이라는 표시가 있었기 때문에 누가 이미 먼저 화장실을 사용하는 것을 알아챌 수 있었다.
바로 뮤텍스 락도 이러한 원리로 작동한다고 보면 되겠다.
만약 임계 구역에 어떤 프로세스가 이미 먼저 진입 했다면 화장실을 사용중이라는 표시와 같은 표시를 해야 한다.
그리고 화장실을 다 사용하면 나갈때 사용중 표지판을 뒤집어 비었음이라고 표시해야 하는 것 처럼 임계 구역에서 프로세스가 나갈 때 이제 임계 구역은 비어있다고 표시를 해줘야 한다.
구체적으로 임계 구역에 프로세스가 있는지에 대한 여부를 나타내는 뮤텍스 락의 형태는 어떻게 될까?
뮤텍스 락의 형태는 전역 변수와 두개의 함수로 구현할 수 있다.
자물쇠(이미 임계 구역에 프로세스가 진입해 있다): 프로세스들이 공유하는 전역 변수 lock
임계 구역을 잠그는 역할:acquire 함수
임계 구역의 잠금을 푸는 역할:release 함수
그럼 이제 우리는 뮤텍스 락을 통하여 어떻게 동기화 기법이 발생하는지 설명 할 수 있다.
우선 임계 구역이 비어있다고 가정할 때 프로세스가 임계 구역에 진입하기 위해서
acquire 함수를 호출한다.
그 다음 acquire 함수를 호출 했으니 전역변수 lock은 true로 바뀔 것이다.
이때 만약 다른 프로세스가 임계 구역에 진입하고 싶다면 lock이 false가 될 때까지 반복적으로 확인하고, 기존에 임계 구역에 있던 프로세스가 나오면서 release 함수를 호출하여 전역 변수 lock을 false로 만든다.
이런식으로 프로세스 동기화가 이루어진다.
세마포는 뮤텍스 락과 비슷하다.
뮤텍스 락은 하나의 공유 자원에 접근하는 프로세스를 상정한 방식이다.
세마포는 공유 자원이 여러개 있을때도 사용할 수 있는 동기화 도구이다.
이제 세마포는 어떻게 동기화가 이루어지는지 형태를 살펴보겠다.
세마포도 뮤텍스 락과 비슷하게 하나의 변수와 두개의 함수로 단순하게 구현할 수 있다.
임계 구역에 진입할 수 있는 프로세스들의 개수를 나타내는 전역변수:S
임게 구역에 들어가도 좋은지, 기다려야 할지를 알려주는 wait 함수
임계 구역 앞에서 기다리는 프로세스에 이제 가도 좋다고 신호를 주는 signal 함수
이제 세마포를 사용해 동기화 기법이 어떻게 이루어지는지 살펴보면
가령 프로세스 P1, P2, P3 이렇게 3개가 있고 P1, P2, P3 순서로 접근한다고,공유 자원은 2개가 있다고 가정을 해보겠다.
공유 자원이 2개가 있으니 전역 변수S는 2가 될 것이다.
이제 전역 변수 S는 0이 되고 다른 프로세스들은 더 이상 임계구역에 진입할 수 없다.
이 과정에서 프로세스 P1이나 P2중에 먼저 끝나는 프로세스는 signal함수를 호출하고 그리하여 전역변수는 S는 다시 1이되고 비로소 P3프로세스도 임계 구역에 진입할 수 있게 된다.
모니터는 공유 자원과 공유 자원에 접근하기 위한 인터페이스를 묶어서 관리를 한다.
프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근할 수 있다.
이를 위해 모니터를 통해 공유 자원에 접근하고자 할 때는 공유 자원을 사용 할 프로세스들을 큐에 삽입하여 삽입된 순서대로 하나씩 공유 자원을 이용하도록 만든다.
그리하여 모니터 안에는 항상 하나의 프로세스만 들어오도록 하여 상호 배제를 위한 동기화를 제공한다.
이 밖에도 프로세스 동기화는 상호 배제를 위한 동기화 뿐만 아니라 실행 순서 제어를 위한 동기화도 제공한다.
실행 순서를 제어하기 위해 조건 변수를 제공한다.
조건 변수로는 wait와 signal 연산을 수행할 수 있다.
우선 wait는 호출한 프로세스의 상태를 대기 상태로 전환하고 일시적으로 조건 변수에 대한 대기 큐에 삽입하는 연산이다.
여기서 착각하면 안되는 점이 조건 변수에 대한 대기 큐와 이전에 설명한 모니터에 진입하기 위해 사용되는 큐는 완전히 다른 큐이다.
조건 변수에 대한 대기 큐에 들어 있는 프로세스는 이미 모니터에 진입하기 위해 사용되는 큐에서 대기하고 있다가 모니터에 들어온 프로세스들이다.
프로세스는 모니터 밖에서 대기 큐에 대기하다가 특정 조건 변수x.wait()을 통해 조건 변수 x에 대한 큐에 삽입한다.
그 후 조건 변수에 대한 큐에서 대기를 하다가 x.signal()를 호출하면 프로세스는 비로소 공유 자원과 함께 실행된다.