동기화
동기화란
동시다발적으로 실행되는 프로세스들은 서로 협력하며 영향을 주고 받는다. 이 과정에서 자원의 일관성을 보장해야 한다. (실행 문맥을 갖는 모든 대상은 동기화 대상이기 때문에 스레드 또한 동기화의 대상이다. 편의상 프로세스만 언급)
동기화의 의미
- 공동의 목적을 위해 동시에 수행되는 프로세스
e.g. 워드 프로세서 프로그램
- 맞춤법 검사 프로세스
- 입력 내용을 화면에 출력하는 프로세스
아무렇게나 마구 실행해도 괜찮을까? => No. 올바른 수행을 위해 프로세스들은 동기화되어야 한다.
동기화란 프로세스들의 수행 시기를 맞추는 것을 말한다.
- 실행 순서 제어: 프로세스를 올바른 순서대로 실행하기
- 상호 배제: 동시에 접근해서는 안되는 자원에 하나의 프로세스만 접근하게 하기
실행 순서 제어를 위한 동기화 - reader writer problem
writer: Book.txt 파일에 값을 저장하는 프로세스
reader: Book.txt 파일에 저장된 값을 읽어들이는 프로세스
reader와 writer 프로세스는 무작정 아무렇게나 실행되어서는 안된다. 실행의 순서가 있기 때문이다. reader 프로세스는 Book.txt 안에 값이 존재한다는 특정 조건이 만족되어야만 실행 가능
상호 배제를 위한 동기화 - Bank account problem
- 공유가 불가능한 자원의 동시 사용을 피하기 위한 동기화
- 한 번에 하나의 프로세스만 접근해야 하는 자원에 동시 접근을 피하기 위한 동기화
ex) 현재 계좌 잔액 10만원
- 프로세스 A는 현재 잔액에 2만원 추가하는 프로세스
- 프로세스 B는 현재 잔액에 5만원 추가하는 프로세스
=> A,B를 동시에 실행하면 17만원이 남아있을까? -> No. 프로세스 A가 끝나기 전에 자원에 접근했기 때문에 전혀 다른 결과가 나온다.
동기화 예제 - Producer & Consumer problem
물건을 계속해서 생산하는 생산자(producer, 프로세스 혹은 스레드)
물건을 계속해서 소비하는 소비자(consumer, 프로세스 혹은 스레드)
총합 변수 공유
생산자 10만번, 소비자 10만번 실행하면 총합은 0이 아닌 값이 되거나 오류가 발생할 수 있다.
- 동기화가 되지 않았기 때문에 발생한 문제
- 동시에 접근해서는 안되는 자원(총합)에 동시에 접근해서 발생한 문제
공유 자원과 임계 구역
공유 자원: 여러 프로세스 혹은 스레드가 공유하는 자원
- 전역 변수, 파일, 입출력장치, 보조기억장치 등
임계 구역: 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
- 앞선 예시의 총합 변수, 잔액 변수 등
- 임계 구역에 진입하고자 하면 진입한 프로세스 이외에는 대기해야 한다.
- 임계 구역에 동시에 접근하면 자원의 일관성이 깨질 수 있다. 이를 레이스 컨디션(race condition)이라고 한다.
운영체제가 임계구역 문제를 해결하는 세 가지 원칙 (상호배제를 위한 동기화를 위한 세 가지 원칙)
1. 상호 배제 (mutual exclusion): 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 들어올 수 없다.
2. 진행 (progress): 임계 구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
3. 유한 대기 (bounded waiting): 한 프로세스가 임계 구역에 진입하고 싶다면 언젠가는 임계 구역에 들어올 수 있어햐 한다. (임계 구역에 들어오기 위해 무한정 대기해서는 안된다.)
동기화 기법
뮤텍스 락, 세마포, 모니터
뮤텍스락
- 상호 배제를 위한 동기화 도구(자물쇠 역할), 뮤텍스 락
- 손님(프로세스)과 탈의실(임계 구역) 비유
- 뮤텍스 락의 단순한 형태: 전역 변수 하나, 함수 두 개
- 자물쇠 역할: 프로세스들이 공유하는 전역 변수 lock
- 임계 구역을 잠그는 역할: acquire함수
- 임계 구역의 잠금을 해제하는 역할: release함수
acquire 함수
- 프로세스가 임계 구역에 진입하기 전에 호출 (탈의실에 들어갈 때는 문을 잠근다)
- 임계 구역이 잠겨 있다면 임계 구역이 열릴 때 까지(lock이 false가 될 때까지) 임계 구역을 반복적으로 확인
- 임계 구역이 열려 있다면 임계 구역을 잠그기(lock을 true로 바꾸기)
acquire() {
while (lock == true) // 만약 임계 구역이 잠겨 있다면
; // 임계 구역이 잠겨있는지 반복적으로 확인
lock == true; // 만약 임계 구역이 잠겨 있지 않다면 임계 구역 잠금
}
=> 바쁜 대기(busy waiting)
release 함수
- 임계 구역에서의 작업이 끝나고 호출
- 현재 잠긴 임계 구역을 열기 (lock을 false로 바꾸기)
release() {
lock = false; // 임계 구역 작업이 끝났으니 잠금 해제
}
세마포
- 좀 더 일반화된 방식의 동기화 도구
- 공유 자원이 여러 개 있는 경우에도 적용 가능
- 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리기
- 임계 구역 앞에서 가도 좋다는 신호를 받으면 임계 구역 진입
세마포의 단순한 형태 - 전역 변수 하나, 함수 두 개
- 임계 구역에 진입할 수 있는 프로세스의 개수 (사용 가능한 공유 자원의 개수)를 나타내는 전역 변수 S
- 임계구역에 들어가도 좋은지, 기다려야할지를 알려주는 wait함수
- 임계구역 앞에서 기다리는 프로세스에 이제 가도 좋다고 신호를주는 signal함수
wait();
// 임계구역
signal();
wait() {
while(S <= 0) // 만일 임계 구역에 진입할 수 있는 프로세스 개수가 0 이하라면
; // 사용할 수 있는 자원이 있는지 반복적으로 확인
S--; // 임계 구역에 진입할 수 있는 프로세스 개수가 하나 이상이면 S를 1 감소시키고 임계 구역 진입
}
signal() {
S++; // 임계구역에서 작업을 마친 뒤 S를 1 증가시킨다.
}
Busy waiting
- 마치 탈의실 문이 열렸는지 닫혔는지 반복적으로 확인하는 것과 같다.
- CPU 사이클 낭비
해결방법
- 사용할 수 있는 자원이 없을 경우 대기 상태로 만듦 (해당 프로세스의 PCB를 대기 큐에 삽입)
- 사용할 수 있는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태로 만듦 (해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입)
세마포를 활용한 실행 순서 동기화
- 세마포의 변수 S를 0으로 두고
- 먼저 실행할 프로세스 뒤에 signal함수,
- 다음에 실행할 프로세스 앞에 wait 변수를 붙이면 된다.
모니터
매번 임계구역 앞뒤로 wait(), signal()을 호출해야할까? 그러다가 실수를 하면??
1. 세마포를 누락한 경우
2. wait와 signal 순서를 헷갈린 경우
3. wait와 signal을 중복해서 사용한 경우
-> 디버깅해도 찾기 어려운 경우가 많다.
그래서 등장한 모니터는 사용자가 다루기에 편한 동기화 도구이다.
모니터
상호 배제를 위한 동기화
- 인터페이스를 위한 큐
- 공유자원에 접근하고자 하는 프로세스를 인터페이스를 위한 큐에 삽입
- 큐에 삽입된 순서대로 한 번에 하나의 프로세스만 공유자원 이용
실행 순서 제어를 위한 동기화
1. 특정 프로세스가 아직 실행될 조건이 되지 않았을 때에는 wait를 통해 실행을 중단한다.
2. 특정 프로세스가 실행될 조건이 충족되었을 떄에는 signal을 통해 실행을 재개한다.
- 조건 변수(condition variable) 이용
- 조건 변수는 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수
- 조건변수.wait(): 대기 상태로 변경, 조건 변수에 대한 큐에 삽입
- 조건변수.signal(): wait()으로 대기 상태로 접어든 조건변수를 실행 상태로 변경
모니터 안에는 하나의 프로세스만이 있을 수 있다.
- wait()를 호출했던 프로세스는 signal()을 호출한 프로세스가 모니터를 떠난 뒤에 수행을 재개
- signal()을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal()을 호출한 프로세스의 수행을 재개
'운영체제' 카테고리의 다른 글
[운영체제] 연속 메모리 할당과 가상 메모리 할당 (0) | 2024.05.15 |
---|---|
[운영체제] 교착상태(DeadLock) (0) | 2024.05.10 |
[운영체제] CPU 스케줄링 (1) | 2024.05.03 |
[운영체제] 프로세스와 스레드 (0) | 2024.04.18 |
[운영체제] 운영체제 기초 (0) | 2024.04.03 |
동기화
동기화란
동시다발적으로 실행되는 프로세스들은 서로 협력하며 영향을 주고 받는다. 이 과정에서 자원의 일관성을 보장해야 한다. (실행 문맥을 갖는 모든 대상은 동기화 대상이기 때문에 스레드 또한 동기화의 대상이다. 편의상 프로세스만 언급)
동기화의 의미
- 공동의 목적을 위해 동시에 수행되는 프로세스
e.g. 워드 프로세서 프로그램
- 맞춤법 검사 프로세스
- 입력 내용을 화면에 출력하는 프로세스
아무렇게나 마구 실행해도 괜찮을까? => No. 올바른 수행을 위해 프로세스들은 동기화되어야 한다.
동기화란 프로세스들의 수행 시기를 맞추는 것을 말한다.
- 실행 순서 제어: 프로세스를 올바른 순서대로 실행하기
- 상호 배제: 동시에 접근해서는 안되는 자원에 하나의 프로세스만 접근하게 하기
실행 순서 제어를 위한 동기화 - reader writer problem
writer: Book.txt 파일에 값을 저장하는 프로세스
reader: Book.txt 파일에 저장된 값을 읽어들이는 프로세스
reader와 writer 프로세스는 무작정 아무렇게나 실행되어서는 안된다. 실행의 순서가 있기 때문이다. reader 프로세스는 Book.txt 안에 값이 존재한다는 특정 조건이 만족되어야만 실행 가능
상호 배제를 위한 동기화 - Bank account problem
- 공유가 불가능한 자원의 동시 사용을 피하기 위한 동기화
- 한 번에 하나의 프로세스만 접근해야 하는 자원에 동시 접근을 피하기 위한 동기화
ex) 현재 계좌 잔액 10만원
- 프로세스 A는 현재 잔액에 2만원 추가하는 프로세스
- 프로세스 B는 현재 잔액에 5만원 추가하는 프로세스
=> A,B를 동시에 실행하면 17만원이 남아있을까? -> No. 프로세스 A가 끝나기 전에 자원에 접근했기 때문에 전혀 다른 결과가 나온다.
동기화 예제 - Producer & Consumer problem
물건을 계속해서 생산하는 생산자(producer, 프로세스 혹은 스레드)
물건을 계속해서 소비하는 소비자(consumer, 프로세스 혹은 스레드)
총합 변수 공유
생산자 10만번, 소비자 10만번 실행하면 총합은 0이 아닌 값이 되거나 오류가 발생할 수 있다.
- 동기화가 되지 않았기 때문에 발생한 문제
- 동시에 접근해서는 안되는 자원(총합)에 동시에 접근해서 발생한 문제
공유 자원과 임계 구역
공유 자원: 여러 프로세스 혹은 스레드가 공유하는 자원
- 전역 변수, 파일, 입출력장치, 보조기억장치 등
임계 구역: 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
- 앞선 예시의 총합 변수, 잔액 변수 등
- 임계 구역에 진입하고자 하면 진입한 프로세스 이외에는 대기해야 한다.
- 임계 구역에 동시에 접근하면 자원의 일관성이 깨질 수 있다. 이를 레이스 컨디션(race condition)이라고 한다.
운영체제가 임계구역 문제를 해결하는 세 가지 원칙 (상호배제를 위한 동기화를 위한 세 가지 원칙)
1. 상호 배제 (mutual exclusion): 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 들어올 수 없다.
2. 진행 (progress): 임계 구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
3. 유한 대기 (bounded waiting): 한 프로세스가 임계 구역에 진입하고 싶다면 언젠가는 임계 구역에 들어올 수 있어햐 한다. (임계 구역에 들어오기 위해 무한정 대기해서는 안된다.)
동기화 기법
뮤텍스 락, 세마포, 모니터
뮤텍스락
- 상호 배제를 위한 동기화 도구(자물쇠 역할), 뮤텍스 락
- 손님(프로세스)과 탈의실(임계 구역) 비유
- 뮤텍스 락의 단순한 형태: 전역 변수 하나, 함수 두 개
- 자물쇠 역할: 프로세스들이 공유하는 전역 변수 lock
- 임계 구역을 잠그는 역할: acquire함수
- 임계 구역의 잠금을 해제하는 역할: release함수
acquire 함수
- 프로세스가 임계 구역에 진입하기 전에 호출 (탈의실에 들어갈 때는 문을 잠근다)
- 임계 구역이 잠겨 있다면 임계 구역이 열릴 때 까지(lock이 false가 될 때까지) 임계 구역을 반복적으로 확인
- 임계 구역이 열려 있다면 임계 구역을 잠그기(lock을 true로 바꾸기)
acquire() {
while (lock == true) // 만약 임계 구역이 잠겨 있다면
; // 임계 구역이 잠겨있는지 반복적으로 확인
lock == true; // 만약 임계 구역이 잠겨 있지 않다면 임계 구역 잠금
}
=> 바쁜 대기(busy waiting)
release 함수
- 임계 구역에서의 작업이 끝나고 호출
- 현재 잠긴 임계 구역을 열기 (lock을 false로 바꾸기)
release() {
lock = false; // 임계 구역 작업이 끝났으니 잠금 해제
}
세마포
- 좀 더 일반화된 방식의 동기화 도구
- 공유 자원이 여러 개 있는 경우에도 적용 가능
- 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리기
- 임계 구역 앞에서 가도 좋다는 신호를 받으면 임계 구역 진입
세마포의 단순한 형태 - 전역 변수 하나, 함수 두 개
- 임계 구역에 진입할 수 있는 프로세스의 개수 (사용 가능한 공유 자원의 개수)를 나타내는 전역 변수 S
- 임계구역에 들어가도 좋은지, 기다려야할지를 알려주는 wait함수
- 임계구역 앞에서 기다리는 프로세스에 이제 가도 좋다고 신호를주는 signal함수
wait();
// 임계구역
signal();
wait() {
while(S <= 0) // 만일 임계 구역에 진입할 수 있는 프로세스 개수가 0 이하라면
; // 사용할 수 있는 자원이 있는지 반복적으로 확인
S--; // 임계 구역에 진입할 수 있는 프로세스 개수가 하나 이상이면 S를 1 감소시키고 임계 구역 진입
}
signal() {
S++; // 임계구역에서 작업을 마친 뒤 S를 1 증가시킨다.
}
Busy waiting
- 마치 탈의실 문이 열렸는지 닫혔는지 반복적으로 확인하는 것과 같다.
- CPU 사이클 낭비
해결방법
- 사용할 수 있는 자원이 없을 경우 대기 상태로 만듦 (해당 프로세스의 PCB를 대기 큐에 삽입)
- 사용할 수 있는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태로 만듦 (해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입)
세마포를 활용한 실행 순서 동기화
- 세마포의 변수 S를 0으로 두고
- 먼저 실행할 프로세스 뒤에 signal함수,
- 다음에 실행할 프로세스 앞에 wait 변수를 붙이면 된다.
모니터
매번 임계구역 앞뒤로 wait(), signal()을 호출해야할까? 그러다가 실수를 하면??
1. 세마포를 누락한 경우
2. wait와 signal 순서를 헷갈린 경우
3. wait와 signal을 중복해서 사용한 경우
-> 디버깅해도 찾기 어려운 경우가 많다.
그래서 등장한 모니터는 사용자가 다루기에 편한 동기화 도구이다.
모니터
상호 배제를 위한 동기화
- 인터페이스를 위한 큐
- 공유자원에 접근하고자 하는 프로세스를 인터페이스를 위한 큐에 삽입
- 큐에 삽입된 순서대로 한 번에 하나의 프로세스만 공유자원 이용
실행 순서 제어를 위한 동기화
1. 특정 프로세스가 아직 실행될 조건이 되지 않았을 때에는 wait를 통해 실행을 중단한다.
2. 특정 프로세스가 실행될 조건이 충족되었을 떄에는 signal을 통해 실행을 재개한다.
- 조건 변수(condition variable) 이용
- 조건 변수는 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수
- 조건변수.wait(): 대기 상태로 변경, 조건 변수에 대한 큐에 삽입
- 조건변수.signal(): wait()으로 대기 상태로 접어든 조건변수를 실행 상태로 변경
모니터 안에는 하나의 프로세스만이 있을 수 있다.
- wait()를 호출했던 프로세스는 signal()을 호출한 프로세스가 모니터를 떠난 뒤에 수행을 재개
- signal()을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal()을 호출한 프로세스의 수행을 재개
'운영체제' 카테고리의 다른 글
[운영체제] 연속 메모리 할당과 가상 메모리 할당 (0) | 2024.05.15 |
---|---|
[운영체제] 교착상태(DeadLock) (0) | 2024.05.10 |
[운영체제] CPU 스케줄링 (1) | 2024.05.03 |
[운영체제] 프로세스와 스레드 (0) | 2024.04.18 |
[운영체제] 운영체제 기초 (0) | 2024.04.03 |