프로세스가 임계구역에 들어가면 임계구역 진입을 잠근다.
다른 프로세스가 임계구역에 들어가고 싶으면 공유 자원이 잠겨있는지 안잠겨있는지 확인하고 기다린다.
이 과정을 구현하기 위해서는 세 가지가 필요하다.
lock
acquire
lock == true
)있으면 열릴 때까지 임계구역을 확인한다.release
lock = False
def acquire():
while lock:
pass
lock = True
def release():
lock = False
acquire()
# 임계구역 코드 #
release()
acquire 함수에서 lock == False
가 될때까지 계속 확인하는 대기 방식을 바쁜 대기 라고 한다
공유 자원이 여러개 있을 경우
(만약 생산자-소비자 문제에서 count
변수가 여러개 있을 경우),
사용 가능한 공유 자원이 하나라도 있으면 임계구역에 접근하면 된다.
프로세스가 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리고, 통과 신호를 받으면 임계 구역에 들어간다.
이 과정을 구현하기 위해서는 세 가지가 필요하다.
S
wait
signal
S = 3
def wait():
while S < 0:
pass
S -= 1
def signal():
S += 1
wait()
# 임계구역 코드 #
signal()
위 과정에서 바쁜 대기의 비효율성을 해결하기 위해, wait
함수는 프로세스 자체를 대기큐로 보낸다.
그리고 다른 프로세스가 signal
함수를 호출하면, 대기중인 프로세스를 준비큐로 옮겨준다.
def wait():
S -= 1
if S < 0:
queue.append(process)
sleep() # 현재 process 를 대기 상태로 바꾸기
def signal():
S += 1
if S <= 0: # 대기 중인 프로세스가 있으면
process = queue.popleft()
wakeup(process) # 꺼낸 process 를 준비 상태로 바꾸기
세마포를 통해 상호 배제 뿐만 아니라 실행 순서도 제어할 수 있다.
S = 0
def 먼저실행프로세스():
# 임계 구역 #
signal()
def 나중실행프로세스():
wait()
# 임계 구역 #
나중실행프로세스
는 임계구역 진입 전 wait 함수를 만나서 대기 상태로 들어가기 때문에, 먼저실행프로세스
가 임계구역에 먼저 진입하도록 제어된다.
임계구역마다 일일이 wait
, signal
함수를 쓰는게 번거로운데, 모니터를 통해 이 과정을 자동으로 처리할 수 있다.
공유 자원을 숨기고, 공유 자원에 접근하기 위한 통로를 묶어서 인터페이스로 관리한다. 프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근할 수 있다.
프로세스가 모니터에 작업을 요청하면 모니터는 이 작업을 큐에 저장한 후 순서대로 작업을 처리하고, 그 결과만 프로세스에게 반환한다. 이를 통해 상호 배제 동기화를 제공한다.
모니터는 실행 순서 제어 동기화도 제공하는데, 여기에는 조건 변수를 사용한다.
조건 변수는 프로세스가 모니터에 진입할 수 있는 조건을 만족할 때까지 들어오지 못하게 대기시키는 역할을 하는데, 조건 변수마다 큐를 가지고 있다.
조건 변수 x
에 대해 wait
를 호출 큐 x
에 프로세스B가 추가되고 실행이 대기됨x
에 대해 signal
을 호출