동기화를 위한 SW 툴들
흔히 비유되는 예시 - 탈의실이 하나 있는 옷 가게
손님은 옷을 입어보기 위해 탈의실에 들어가야 하고, 탈의실은 딱 하나 존재한다.
손님을 프로세스라 본다면, 탈의실은 자원 및 critical section으로 볼 수 있다.
탈의실이 이용 중인지 알 수 있는 방법은? 자물쇠!
자물쇠가 걸려 있는지 여부에 따라 탈의실 이용 여부를 결정하고 기다림.
→ 이와 같은 비유를 그대로 나타낸 것이 mutex lock 🔒
lock을 걸어 현재 하나의 프로세스가 critical section 안에 있음을 알려, 다른 프로세스의 진입을 대기시킨다.
lock
프로세스들이 공유하는 전역 변수
acquire()
acquire() {
while (!lock) { // lock이 잠겨 있다면 lock이 잠겨 있는지를 계속해서 확인
// busy wait
}
lock = true // lock이 풀려 있다면 lock을 걸어 critical section 잠금
}
busy wait
: lock이 잠겨 있는지 계속해서 확인하며 대기 release()
release() {
lock = false
}
하나의 프로세스만 critical section으로 진입하게 하는 로직
acquire()
// critical section
release()
S
사용 가능한 공유 자원의 개수(== critical section에 진입할 수 있는 프로세스의 개수)
wait()
wait() {
// critical section에 진입할 수 있는 프로세스 개수가 0개 이하이면
// 사용할 수 있는 자원이 있는지 계속해서 확인
while (S<=0)
S -= 1 // 1개 이상이면 S를 1 감소시킨 후 critical section 진입
}
busy wait
signal()
signal() {
S += 1 // critical section에서 작업을 마친 후 S를 1 증가시킴
}
wait()
// critical section
signal()
busy wait
을 없애기 위해서
wait() 에서 사용할 수 있는 자원이 없을 경우 (S ≤ 0) 해당 프로세스를 waiting 상태로 만들고,
해당 프로세스의 pcb를 semaphore waiting queue에 넣는다.
그리고 signal()이 호출되면, 해당 프로세스를 ready queue에서 제거하고,
ready 상태로 변경하여 ready queue로 옮겨 준다.
wait() {
S -= 1
if S < 0 {
queue에 넣기 // pcb를 waiting queue에 넣기
sleep() // waiting 상태
}
}
signal() {
S += 1
if S <= 0 { // 대기 중인 프로세스가 존재하는 경우
queue에서 해당 프로세스 p 제거
wakeup(p) // 프로세스 p를 waiting -> ready
}
}
세마포어로 실행 순서도 제어할 수 있다.
p1 → p2 순서로 실행되게 하려면?
S를 0으로 두고
먼저 실행할 프로세스 p1 뒤에 signal()
다음에 실행할 프로세스 p2 앞에 wait()
p1이 먼저 실행되면 critical section에 들어가고, p2가 먼저 실행되어도, wait()을 만나 큐로 들어간다.
사용자가 사용하기에 편리한 동기화 도구
모니터도 mutual exclusion과 실행 순서 제어를 위한 동기화 모두 제공한다.
우리는 어떤 공유 자원에 대해 모니터를 지정해 두면, 데이터 접근을 위해서 모니터에 진입해야 한다.
conditional variable
) 사용wait()
/ signal()
연산 수행x.wait()
waiting
상태로 전환하고, conditional variable
waiting queue에 삽입x.signal()
이 호출될 때까지 실행 중지됨x.signal()
conditional variable
에 대해 waiting 상태에 있던 프로세스가 깨어나 모니터 안으로 들어온다.
혼자 공부하는 운영체제