프로세스들 사이의 수행 시기를 맞추어 특정 자원에 접근할 때 한 개의 프로세스만 접근하게 하거나 프로세스를 올바른 순서대로 실행하게 하는 것
(프로세스 이외에도 실행의 흐름을 갖는 모든 것은 동기화의 대상)
물건이 처음에 10개 있었다고 가정
총합 = 10
생산자(){
버퍼에 데이터 삽입
'총합' 변수 1 증가
}
소비자(){
버퍼에서 데이터 빼내기
'총합' 변수 1 감소
}
생산자를 100,000번, 소비자를 100,000번 동시에 실행
생산자 프로세스와 소비자 프로세스가 제대로 동기화되지 않은 상황이라면 합계가 10아 아닌 다른 수가 되거나 실행 중 오류가 발생할 수 있음
(즉, producer, consumer가 동시에 접근해서는 안 되는 자원에 동시에 접근하여 발생하는 문제)
참고: https://github.com/kangtegong/self-learning-cs/blob/main/producer_consumer/producer_consumer.cpp
상호 배제를 위한 동기화를 위한 세 가지 원칙
- 상호 배제: 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 임계 구역에 들어올 수 없다
- 진행: 임계 구역에 어떤 프로세스도 진입하지 않았다면 임계 구역에 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
- 유한 대기: 한 프로세스가 임계 구역에 진입하고 싶다면 그 프로세스는 언젠가 임계 구역에 들어올 수 있어야 한다. (무한정 대기 X)
동시에 접근해서는 안 되는 자원에 동시에 접근하지 않도록 만드는 도구, 즉 상호 배제를 위한 동기화 도구
acquire 함수 | release 함수 |
---|---|
임계 구역을 잠그는 역할, 프로세스가 임계 구역에 진입하기 전에 호출 | 임계 구역에서의 작업이 끝나고 호출하는 함수, 임계 구역을 열어줌 |
임계 구역이 잠겨있는 경우: 임계 구역이 열릴 때까지 임계 구역을 반복적으로 확인 바쁜 대기 | |
임계 구역이 열려있는 경우: 임계 구역을 잠금 |
acquire(){
while (lock == true) #임계 구역이 잠겨 있다면
; #임계 구역이 잠겨 있는지를 반복적으로 확인
lock = true; #임계 구역이 잠겨 있지 않다면 임계 구역 잠금
}
// 임게 구역
release(){
lock = false; #임계 구역 작업이 끝났으므로 잠금 해제
}
뮤텍스 락 | 세마포 |
---|---|
하나의 공유 자원에 접근하는 프로세스를 상정한 동기화 도구 | 공유 자원이 여러 개 있는 경우에도 적용이 가능한 동기화 도구 |
- 이진 세마포: 뮤텍스 락과 유사한 개념
- 카운팅 세마포: 여러 공유 자원을 다룰 수 있음
전역 변수 S | wait 함수 (P, down) | signal 함수 (V, up) |
---|---|---|
임계 구역에 진입할 수 있는 프로세스의 개수 | 임계 구역에 들어가도 좋은지, 기다려야 할지를 알려주는 함수 | 임계 구역 앞에서 기다리는 프로세스에 '가도 좋다'고 신호를 주는 함수 |
wait(){
while (S <= 0) #만일 임계 구역에 진입할 수 있는 프로세스의 개수가 0 이하라면
; #사용할 수 있는 자원이 있는지 반복적으로 확인
S--; #임계 구역에 진입할 수 있는 프로세스 개수가 하나 이상이면 S를 1 감소시키고 임계 구역 진입
}
// 임계 구역
signal(){
S++ #임계 구역에서의 작업을 마친 뒤 S를 1 증가
}
ex) P1, P2, P3의 세 개의 프로세스가 두 개의 공유자원에 P1, P2, P3 순서로 접근한다고 가정 (S=2)
step | 작업 | S | 임계 구역 진입 |
---|---|---|---|
1 | 프로세스 P1 wait 호출 | S -= 1 ( S=1) | O |
2 | 프로세스 P2 wait 호출 | S -= 1 ( S=0) | O |
3 | 프로세스 P3 wait 호출 | 무한히 반복하며 S 확인 | X |
4 | 프로세스 P1 임계 구역 작업 종료, signal 호출 | S += 1 ( S=1) | - |
5 | 프로세스 P3 S = 1 확인 | S -= 1 ( S=0) | O |
무한히 반복하며 S를 확인 = CPU 주기 낭비
wait 함수: 사용할 수 있는 자원이 없을 경우 해당 프로세스 상태를 대기 상태로 만듦
프로세스의 PCB를 세마포를 위한 대기 큐에 집어 넣음
다른 프로세스가 임계 구역에서의 작업이 끝나고 signal 함수를 호출
signal 함수는 대기 중인 프로세스를 대기 큐에서 제거
프로세스 상태를 준비 상태로 변경한 뒤 준비 큐로 옮김
wait(){
S--;
if (S < 0){
add this process to Queue; #해당 프로세스 PCB를 대기 큐에 삽입
sleep(); # 대기 상태
}
}
// 임계 구역
signal(){
S++;
if (S <= 0){
remove a process p from Queue; #대기 큐에 있는 프로세스 p를 제거
wakeup(p); # 프로세스 p를 대기 상태에서 준비 상태로 만듦
}
}
step | 작업 | S | 상태 |
---|---|---|---|
1 | 프로세스 P1 wait 호출 | S -= 1 ( S=1) | 임계 구역 진입 |
2 | 프로세스 P2 wait 호출 | S -= 1 ( S=0) | 임계 구역 진입 |
3 | 프로세스 P3 wait 호출 | S -= 1 ( S=-1) | 본인의 PCB를 대기 큐에 넣고 대기 상태로 전환 |
4 | 프로세스 P1 임계 구역 작업 종료, signal 호출 | S += 1 ( S=0) | P3를 대기 큐에서 꺼내 준비 큐로 옮김 |
5 | 프로세스 P3 S = 0 확인 | S=0 | 임계 구역 진입 |
6 | 프로세스 P2 임계 구역 작업 종료, signal 호출 | S += 1 ( S=1) | - |
7 | 프로세스 P3 임계 구역 작업 종료, signal 호출 | S += 1 ( S=2) | - |
공유 자원과 공유 자원에 접근하기 위한 인터페이스를 묶어 관리
모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입 &
큐에 삽입된 순서대로 하나씩 공유 자원을 이용하도록 함
(즉, 모니터는 공유 자원을 다루는 인터페이스를 접근하기 위한 큐를 만들고, 모니터 안에 항상 하나의 프로세스만 들어오도록 하여 상호 배제를 위한 동기화를 제공)
실행 순서 제어를 위한 동기화를 제공
- 특정 프로세스가 아직 실행될 조건이 되지 않았을 때에는 wait을 통해 실행 중단
- 특정 프로세스가 실행될 조건이 충족되었을 때에는 signal을 통해 실행을 재개
모니터에 진입하기 위해 삽입되는 큐 | wait가 호출되어 실행이 중단된 프로세스들이 삽입되는 큐 |
---|---|
상호 배제를 위한 큐 | 조건 변수에 대한 큐 |
모니터에 한 번에 하나의 프로세스만 진입하도록 하기 위해 만들어진 큐 | 모니터에 이미 진입한 프로세스의 실행 조건이 만족될 때까지 잠시 실행이 중단되어 기다리기 위해 만들어진 큐 |
확인문제
p. 363
1번 뮤텍스 락과 세마포에 대한 설명으로 옳지 않은 것은?
(4) 세마포를 이용하면 반드시 바쁜 대기를 해야 한다.
대기 상태로 접어들게 할 수도 있음
참고문헌
https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=299014282&start=slayer