동기화 기법
뮤텍스 락
- 상호 배제를 위한 동기화 도구 (자물쇠 역할)
- 전역 변수 하나, 함수 두개
lock
: 자물쇠 역할의 전역 변수acquire
: 임계 구역을 잠그는 함수release
: 임계 구역의 잠금을 해제하는 함수
void acquire()
{
while (lock == true)
; /* 임계 구역이 잠겨 있는지를 잠겨 있지 않을 때까지, 반복 확인 */
lock = true; /* 임계 구역이 잠겨 있지 않다면, 임계 구역을 잠금*/
}
void release()
{
lock = false; /* 임계 구역 작업이 끝난 후 잠금 해제*/
}
void SomeThread()
{
acquire(); /* 자물쇠가 잠겨있는지 확인 후, 자물쇠가 풀릴 때까지 기다렸다가 자물쇠를 잠그고 들어옴 */
// 임계 구역
release(); /* 자물쇠를 풂 */
}
바쁜 대기
while (lock == true) /* 만약 임계 구역이 잠겨 있다면 */
; /* 임계 구역이 잠겨 있는지를 반복적으로 확인 */
문이 잠겨있는지를 계속 덜컹거리며 확인 (CPU 자원 계속 소모)
세마포
- 좀 더 일반화된 방식의 동기화 도구
- 공유 자원이 여러 개 있는 경우에도 적용 가능
- 여기에선 카운팅 세마포를 지칭 (이진 세마포는 뮤텍스 락과 유사)
- 세마포의 단순한 형태 : 전역 변수 하나, 함수 두 개
S
: 임계 구역에 진입할 수 있는 프로세스 개수를 나타내는 전역 변수wait
: 임계 구역에 들어가도 좋은지, 기다려야 할지를 알려주는 함수signal
: 임계 구역 앞에서 기다리는 프로세스에게 ‘이제 가도 좋다’고 신호를 주는 함수 ```c++ void SomeThread() { wait(); // 임계 구역 signal(); }
void wait() { while ( S <= 0) ; S–; } void signal() { S++; }
## 바쁜 대기 해결 방법
* 사용할 수 있는 자원이 없을 경우 `대기 상태`로 만듦
(해당 프로세스의 PCB를 대기 큐에 삽입)
* 사용할 수 있는 자원이 생겼을 경우, 대기 큐의 프로세스를 `준비 상태`로 만듦
(해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입)
## 실행 순서 제어 동기화
```c++
int S = 0;
void P1() // 먼저 실행 되어야 함
{
// 임계 구역
signal();
}
void P2() // 나중에 실행 되어야 함
{
wait();
// 임계 구역
}
모니터
뮤텍스 락, 세마포 같은 경우는 앞뒤로 함수를 붙여줘야 해서 실수가 발생할 수 있고, 실수로 누락하거나 순서를 헷갈리거나, 중복해서 같은 함수를 붙일 시 디버깅이 어렵다.
모니터
: 사용자가 사용하기 편한 동기화 도구
상호 배제를 위한 동기화
- 인터페이스를 위한 큐
- 공유 자원에 접근하고자 하는 프로세스를 (공유 자원을 위한) 큐에 삽입
- 큐에 삽입된 순서대로 (한 번에 하나의 프로세스만) 공유 자원 이용
실행 순서 제어를 위한 동기화
- 조건 변수(Condition Variable)를 이용
- 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수
- 조건 변수.wait() : 대기 상태로 변경, 조건 변수에 대한 큐에 삽입
- 조건 변수.signal() : wait()로 대기 상태가 된 프로세스를 준비 상태로 변경