목차
- 동기화
- 실행 순서 제어를 위한 동기화
- 상호 배제를 위한 동기화
- 공유 자원과 임계 구역
- 동기화 기법(뮤텍스 락, 세마포, 모니터)
동기화
동시다발적으로 실행되는 프로세스들은 서로 협력하며 영향을 주고받는다.
이 과정에서 자원의 일관성을 보장해야 한다. => 프로세스들의 동기화를 고려해야 한다.
동기화의 의미
공동의 목적을 위해 동시에 수행되는 프로세스(프로세스 + 스레드)
※ 이 글은 프로세스와 스레드를 구분하지 않고 합쳐 프로세스로 정의하겠습니다.
예시)
- 워드 프로세서 프로그램
- 맞춤법 검사 프로세스
- 입력 내용을 화면에 출력하는 프로세스
- ... 여러 프로세스
Q. 프로세스 아무렇게나 마구 실행해도 괜찮을까?
A. NO!!! 올바른 수행을 위해 프로세스들은 동기화되어야 한다.(자원의 일관성 보장해줘야 함)
(프로세스) 동기화란?
프로세스들의 수행 시기를 맞추는 것
(실행의 문맥을 갖는 모든 대상은 동기화 대상이기에 스레드도 동기화 대상입니다.)
- 실행 순서 제어: 프로세스를 올바른 순서대로 실행하기
- 상호 배제: 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하게 하기
실행 순서 제어를 위한 동기화
실행 순서 제어를 위한 동기화: (reader writer problem)
- Writer: Book.txt 파일에 값을 저장하는 프로세스
- Reader: Boox.txt 파일에 저장된 값을 읽어들이는 프로세스
Reader와 Writer 프로세스는 무작정 아무렇게나 실행되어선 안된다.
실행의 순서가 있기 때문이다.
(Reader 프로세스는 'Book.txt 안에 값이 존재한다' 는 특정 조건이 만족되어야만 실행 가능)
정리
동시다발적으로 실행되는 두 개 이상의 프로세스가 있을 때 실행 순서를 동기화 해주는 것이
실행 순서 제어를 위한 동기화
상호 배제를 위한 동기화
상호 배제를 위한 동기화: Bank account Problem
- 공유가 불가능한 자원의 동시 사용을 피하기 위한 동기화
- 한번에 하나의 프로세스만 접근해야 하는 자원에 동시 접근을 피하기 위한 동기화
예시)
현재 계좌에 잔액: 10만원
- 프로세스 A는 현재 잔액에 2만원을 추가하는 프로세스
- 프로세스 B는 현재 잔액에 5만원을 추가하는 프로세스
- 동시에 실행한다고 가정
프로세스 A
- 계좌의 잔액을 읽어 들인다.
- 읽어 들인 잔액에 2만 원을 더한다.
- 더한 값을 저장한다.
프로세스 B
- 계좌의 잔액을 읽어 들인다.
- 읽어 들인 잔액에 5만 원을 더한다.
- 더한 값을 저장한다.
"프로세스 A, 프로세스 B를 동시에 실행한다면 당연히 17만원이 계좌에 남을까?"
현재 계좌에 잔액: 15만 원..
이유는 무엇일까?
"프로세스 A와 B는 잔액이라고 하는 데이터를 동시에 사용을 하는데 프로세스의 실행이 전부 다 끝나버리기도 전에
프로세스 B가 잔액이라고 하는 자원(데이터)에 접근했기 때문"
<= 한 프로세스가 잔액이라는 데이터에 접근할 때는 다른 프로세스는 잔액이라는 데이터에 접근하면 안됨
쉽게 말하면 동시에 접근해서는 안되는 "잔액"에 동시에 접근했기 때문!!!!!
동기화 예제
Product & Consumer problem
- 물건을 계속해서 생산하는 생산자(producer, 프로세스 혹은 스레드)
- 물건을 계속해서 소비하는 소비자(consumer, 프로세스 혹은 스레드)
- "총합" 변수 공유 가정
이 상태에서 무작정 동시에 생산자를 100,000번, 소비자를 100,000번 실행하면 '총합' 은?
=> 때로는 0과 다른 값이 되거나, 오류가 발생하기도 => 동기화가 되지 않았기 때문에 발생한 문제
=> 동시에 접근해서는 안되는 자원(총합)에 동시에 접근해서 발생한 문제
공유 자원과 임계 구역
공유 자원: 여러 프로세스 혹은 스레드가 공유하는 자원
- 전역 변수, 파일, 입출력장치, 보조기억장치, ...
임계 구역: 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
- 앞선 예시의 '총합' 변수, '잔액' 변수, ...
임계 구역에 진입하고자 하면 진입한 프로세스 이외에는 대기해야 한다.
임계 구역에 동시에 접근하려고 하면? => 당연히 문제가 생긴다.
- 임계 구역에 동시에 접근하면 자원의 일관성이 깨질 수 있다.
- 이를 레이스 컨디션(race condition) 이라고 한다.
개발자가 작성하는 소스코드(고급언어)는 한 줄일지 몰라도 컴퓨터 내부에서는 여러 줄이다.
운영체제가 임계구역 문제를 해결하는 세 가지 원칙
(상호 배제를 위한 동기화를 위한 세 가지 원칙)
상호 배제(mutual exclusion): 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 들어올 수 없다.
진행(progress): 임계 구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 들어갈 수 있어야 한다.
유한 대기( bounded waiting): 한 프로세스가 임계 구역에 진입하고 싶다면 언젠가는 임계 구역에 들어올 수 있어야 한다.
(임계 구역에 들어오기 위해 무한정 대기해서는 안된다.)
동기화 기법
1. 뮤텍스 락
뮤텍스 락: 상호 배제를 위한 동기화 도구(자물쇠 역할)
뮤텍스 락의 단순한 형태
- 전역 변수 하나, 함수 두개
- 자물쇠 역할: 프로세스들이 공유하는 전역 변수 lock
- 임계 구역을 잠그는 역할: acquire 함수
- 임계 구역의 잠금을 해제하는 역할: release 함수
acquire 함수
- 프로세스가 임계 구역에 진입하기 전에 호출
- 임계 구역이 잠겨 있다면
- 임계 구역이 열릴 때까지(lock이 false가 될 때까지) 임계 구역을 반복적으로 확인
- 임계 구역이 열려 있다면
- 임계 구역을 잠그기(lock을 true로 바꾸기)
release 함수
- 임계 구역에서의 작업이 끝나고 호출
- 현재 잠긴 임계 구역을 열기(lock을 false로 바꾸기)
바쁜 대기(busy waiting)
- 마치 탈의실 문이 잠겨 있는지 아닌지 쉴 새 없이 덜컥 덜컥 확인해보는 것과 같기 때문에 좋은 방식이 아니다.
- 반복적으로 무한히 대기하면서 임계구역이 열려 있는지 아닌지 확인해보는 방식을 바쁜 대기라고 부른다.
2. 세마포
- 좀 더 일반화된 방식의 동기화 도구
- 공유 자원이 여러 개 있는 경우에도 적용 가능
- 세마포의 종류(이진 세마포, 카운팅 세마포) 중 카운팅 세마포를 다룬다.
- 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리기
- 임계 구역 앞에서 가도 좋다는 신호를 받으면 임계 구역 진입
세마포의 단순한 형태
- 전역 변수 하나, 함수 두개
- 임계 구역에 진입할 수 있는 프로세스의 개수(사용 가능한 공유 자원의 개수)를 나타내는 전역 변수 S
- 임계 구역에 들어가도 좋은지, 기다려야 할지를 알려주는 wait 함수
- 임계 구역 앞에서 기다리는 프로세스에 '이제 가도 좋다' 고 신호를 주는 signal 함수
세 개의 프로세스 P1, P2, P3가 두개의 공유 자원(S=2)에 P1, P2, P3 순서로 접근한다고 가정
세마포 방식에도 무한히 대기하면서 임계구역이 열려 있는지 아닌지 확인
(while(S <= 0) ;) 한다는 점에서 바쁜 대기(Busy waiting)이 적용되어 있다.
Busy waiting
마치 탈의실 문이 열렸는지/닫혔는지 반복적으로 확인하는 것과 같다.
=> CPU 사이클 낭비!
해결 방법
- 사용할 수 있는 자원이 없을 경우 대기 상태로 만듦
- (해당 프로세스의 PCB를 대기 큐에 삽입)
- 대기 상태이므로 CPU 사이클이 필요없다!
- 사용할 수 있는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태로 만듦
- (해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입)
세 개의 프로세스 P1, P2, P3가 두개의 공유 자원(S=2)에 P1, P2, P3 순서로 접근한다고 똑같이 가정
세마포를 활용한 실행 순서 동기화
세마포는 상호 배제를 위한 동기화 뿐만 아니라 실행 순서 보장도 가능하다.
- 세마포의 변수 S를 0으로 두고,
- 먼저 실행할 프로세스 뒤에 signal 함수
- 다음에 실행할 프로세스 앞에 wait 함수를 붙이면 된다.
3. 모니터
"매번 임계 구역 앞뒤로 wait, signal 함수를 호출해야 할까?"
"그러다 실수를 하면 어떻하지?"
- 그래서 등장한 모니터
- 사용자(개발자)가 다루기에 편한 동기화 도구
- 상호 배제를 위한 동기화 뿐만 아니라 실행 순서 제어를 위한 동기화까지도 제공
- 모니터 안에는 하나의 프로세스만이 있을 수 있다.
상호 배제를 위한 동기화
- 인터페이스를 위한 큐
- 공유자원에 접근하고자 하는 프로세스를 (인터페이스를 위한) 큐에 삽입
- 큐에 삽입된 순서대로 (한 번에 하나의 프로세스만) 공유 자원 이용
실행 순서 제어를 위한 동기화
- 조건 변수(condition variable) 이용
- 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수
- 조건 변수.wait( ): 대기 상태로 변경, 조건 변수에 대한 큐에 삽입
- 조건 변수.signal( ): wait( )으로 대기 상태로 접어든 조건 변수를 실행 상태로 벼녁ㅇ
모니터 안에는 하나의 프로세스만이 있을 수 있다.
방법 2가지
- wait( )를 호출했던 프로세스(프로세스 A)는 signal( )을 호출한 프로세스(프로세스 B)가 모니터를 떠난 뒤에 수행을 재개
- signal( )을 호출한 프로세스(프로세스 B)의 실행을 일시 중단(대기 상태)하고 자신(프로세스 A)이 실행된 뒤 다시 signal( )을 호출한 프로세스(프로세스 B)의 수행을 재개
프로세스 B가 앞에 있는 프로세스 A보다 빨리 실행되어야 하는 경우를 가정
정리
- 특정 프로세스가 아직 실행될 조건이 되지 않았을 때에는 (프로세스 A의) wait를 통해 실행을 중단한다.
- 특정 프로세스가 실행될 조건이 충족되었을 때에는 (프로세스 B의) signal을 통해 실행을 재개한다.
해당 포스팅에 나온 글과 이미지들은 강민철 저자님의 혼자 공부하는 컴퓨터 구조 + 운영체제의 책과 강의를 참고하여 만들어졌습니다.
책에서 보다 깊게 나오는 내용이 있으므로 한번 구매하고 보셔도 좋을 것 같습니다.
'CS' 카테고리의 다른 글
[CS] 운영체제의 메모리 관리 방식 페이징 (0) | 2024.05.26 |
---|---|
[CS] 교착 상태 (0) | 2024.05.26 |
[CS] CPU 스케줄링 알고리즘 (1) | 2024.05.25 |
[CS] 스레드 (0) | 2024.05.25 |
[CS] 프로세스 (0) | 2024.05.24 |