임계구역 문제를 해결하는 단순한 방법은 잠금을 이용하는 것이다.
피터슨 알고리즘
lock1과 lock2 그리고 turn이라는 변수를 이용해 구현한다.
피터슨 알고리즘은 임계구역 해결의 3가지 조건을 만족하지만 2개의 프로세스만 사용 가능하다는 한계가 있다.
여러 프로세스를 사용하려면 공유변수를 추가해야한다.
데커 알고리즘
하드웨어의 도움 없이도 임계구역 문제를 해결할 수 있다.
하지만 매우 복잡하다는 단점이 있다.
세마포어
다익스트라가 제안한 알고리즘으로 간단하고 사용하기 쉬운 알고리즘이다.
세마포어는 임계구역에 진입하기 전에 스위치를 사용 중으로 놓고 임계구역에 들어간다. 작업을 마치면 다음 프로세스에 동기화 신호를 보낸다.
Semaphore(n);
P();
/* 임계 구역 */
V();
위는 세마포어 코드이다.
Semaphore(n) : 전역 변수 RS를 n으로 초기화 한다. RS는 현재 사용 가능한 자원의 수 이다.
P() : 잠금을 수행하는 코드로 RS가 0보다 크면 1만큼 감소시키고 임계구역에 진입, 0보다 작으면 0보다 커질때까지 기다린다.
V() : 잠금 해제와 동기화를 수행하는 코드로, RS를 1 증가시키고 wake_up 신호를 보낸다.
세마포어에서 잠금이 해제되기를 기다리는 프로세스들은 세마포어 큐에 저장되어 있다가 wake_up신호를 받고나서 큐에서 나와 임계구역에 진입한다. 따라서 busy waiting을 하는 프로세스가 없다.
모니터
세마포어의 큰 문제는 잘못된 사용으로 인해 임계구역이 보호받지 못한다는 것이다.
사용자가 고의로 세마포어를 사용하지 않거나 잘못 사용하는 경우를 막을 수 없다는 것이다. 따라서 이를 자동으로 처리하고 구현한 것이 모니터이다.
모니터는 공유 자원을 내부적으로 숨기고 공유 자원에 접근하기 위한 인터페이스만 제공해서 자원을 보호하고 프로세스 간에 동기화를 시킨다. 시스템 호출과 같은 개념이다.
monitor shared_balance{
private :
int balance = 10;
boolean busy=false;
condition mon;
public :
increase(int amount) {
if(busy==true) mon.wait();
busy=true;
balance=balance+amount;
mon.signal();
}
}
위는 모니터 코드이다. busy는 잠금 역할, mon은 잠금 해제 역할을 하며 공유 변수는 balance이다. 이 변수는 increase()를 통해서만 값을 변경할 수 있다. increase()는 임계구역이 잠겼는지 확인한 후 예금액을 증가시킨다.
모니터를 사용하면 P()와 V()를 사용할 필요가 없이 increase()만 사용하면 된다.
모니터는 임계구역 보호와 동기화를 위해 내부적으로 상태 변수를 사용한다.
상태 변수에는 wait()와 signal()이 있다.
wait() : 모니터 큐에서 자신의 차례가 올 때까지 기다린다. 세마포어의 P()에 해당한다.
signal() : 모니터 큐에서 기다리는 다음 프로세스에 순서를 넘겨준다. 세마포어의 V()에 해당한다.
'프로그래밍 이론 & 책 > 운영체제' 카테고리의 다른 글
[운영체제] 6.2 교착 상태 필요조건 (0) | 2020.05.27 |
---|---|
[운영체제] 6.1 교착 상태의 개요 (0) | 2020.05.27 |
[운영체제] 5.2 공유 자원과 임계구역 (0) | 2020.05.26 |
[운영체제] 5.1 프로세스 간 통신 (0) | 2020.05.26 |
[운영체제] 4.4 스케줄링 알고리즘 (0) | 2020.05.25 |