여러 프로세스나 스레드가 공유자원에 접근하거나
특정 조건을 만족시키기 위해서 서로 기다리는 과정을 의미한다.즉 프로세스들 사이에 수행시기를 맞추는 것을 의미한다.
수행 시기를 맞춘다는 것은 크게 두가지를 말한다.
실행 순서 제어
프로세스를 올바른 순서대로 실행한다.상호 배제
공유 자원에는 반드시 단 하나의 프로세스만 접근하게 한다.
따라서 동기화는 실행 순서를 위한 동기화가 있고
상호 배제를 위한 동기화가 있다.
다음 두 프로세스가 동시에 실행 중이라고 가정하자.
Writer
: Book.txt 파일에 값을 저장하는 프로세스
Reader
: Book.txt 파일에 저장된 값을 읽는 프로세스
이 두 프로세스는
순서가 매우 중요
하다.
반드시 파일에 값을 저장하고 저장된 값을 읽어야한다.이렇게 동시에 실행되는 프로세스를 올바른 순서대로 실행하는 것을
실행 순서를 제어하기 위한 동기화
이다.
공유가 불가능한 자원의 동시 사용을 피하기 위해 사용하는 알고리즘이다.
은행 계좌에 대한
두 개의 별도의 트랜잭션
이 있다고 가정하자.
각각은 같은 계좌에서 돈을 인출하려고 하는데
만약두 트랜잭션이 동시에 실행
되면
인출이 2번 되는 등계좌 잔액이 잘못 계산
될 수 있다.이러한 현상을 막기 위해 동기화가 필요하며
이런 메커니즘을상호 배제를 위한 동기화
라고 한다.
생산자는 데이터를 생성하고 버퍼에 추가하며,
소비자는 버퍼에서 데이터를 제거하고 사용한다.이 두 과정은 동시에 발생할 수 있기 때문에 상호 배제 동기화가 필요하다.
또한
생산자
는버퍼 오버플로우
를 방지하기 위해 버퍼가 꽉차면데이터를 추가하지 못하도록
해야한다.
소비자
는버퍼 언더플로우
를 방지하기위해 버퍼가 비어 있으면데이터를 소비하지 못하도록
해야한다.
공유 자원은 여러 프로세스들이 같이 사용하는 자원을 말한다.
예시로는
전역 변수
,파일
,입출력장치
,보조기억장치
등이 있다.
임계 구역
은동시에 접근하면 "문제가 생기는 공유 자원"에 접근하는 코드 영역
말한다.임계 구역에는 반드시 하나의 프로세스만 접근해야 한다.
만약 다른 프로세스가 임계 구역을 점거하고 있다면 대기해야한다.
잘못된 실행으로 인해
여려 프로세스가 동시 다발적으로 임계 구역의 코드를 실행
하여
문제를 발생하는 경우를 말한다.이 경우
데이터의 일관성
을 해치게 된다.
개발자가 작성하는 코드는 고급 언어이다.
하지만 컴퓨터는 고급언어를 저급언어로 변환하여 실행한다.한 줄의 고급언어를 저급언어로 변환하면 여러 줄이 될 수 있다.
그 여러줄에 저급언어가 실행되는 과정에서 문맥교환이 일어나면
자원의 일관성이 깨질 수 있다.예를 들어
x = x + 1
을 저급언어로 변경하면 다음과 같이 될 수 있다.
메모리에서 x의 값을 가져온다
그 값을 1만큼 증가시킨다
증가된 값을 다시 x 에 저장한다
동일한 스레드가 동시에
x = x + 1
을 수행한다고 가정하자
위 세단계가 다 완료되기전에 문맥교환이 발생하고 다른 스레드가 동일한 작업을 수행하기 시작하면
원래 기대한 값보다 최종 값이 1 적게 증가될 수도 있다.두 스레드가 거의 동시에 x의 원래 값을 읽고 그 값에 1을 더하여
동일한 값을 다시 x에 저장할 수 있기 때문이다.
한 프로세스가 임계 구역에 진입 했다면
다른 프로세스는 임계 구역에 들어올 수 없다.
임계 구역에 어떤 프로세스도 진입하지 않았다면
임계 구역에 진입하고자하는 프로세스는 들어갈 수 있어야만 한다.
임계 구역에 들어오기 위해서 무한정 대기해서는 안된다.
상호 배제를 위한 동기화 기법이다.
임계 구역에 진입하는 프로세스는
다른 프로세스가 진입하지 못하도록 공유자원에 Lock을 건다.다른 프로세스는 공유자원이 Lock 상태라면 기다리고
그렇지 않다면 임계 구역에 진입한다.
전역 변수 Lock
자물쇠의 상태를 저장하는 변수
acquire 함수
자물쇠를 잠그는 함수
release 함수
자물쇠를 푸는 함수
프로세스가 임계 구역에 진입하기 전에 호출하는 함수
만약
임계 구역이 잠겨있다면
임계 구역이 열릴 때까지(Lock이 false) 가 될때까지 반복적으로 확인
하고 ,
임계 구역이 열려있다면
임계 구역을 잠그는(Lock을 true로 바꾸는) 함수
이다.acquire() { while(Lock == true){ // 임게 구역이 잠겨 있는지 확인, 이러한 대기 방식을 busy wait 라고한다. } Lock = true; }
임계 구역에서의 작업이 끝나고 호출하는 함수이다.
잠긴 임계 구역을 열어주는(Lock을 false로 바꾸는) 함수
이다.release() { Lock = false; }
뮤텍스
는같은 공유자원의 개수가 1개 있는 경우를 가정
하고 만든 동기화 도구이다.
카운팅 세마포
의 경우같은 공유 자원의 개수가 여러 개 있는 경우를 가정
하고 만든 동기화 도구이다.
전역 변수 S
임계 구역에 진힘할 수 잇는 프로세스의 개수(사용가능한 공유자원의 개수)의 역할
wait 함수
임계 구역에 갈 수 있는지 기다려야하는지 알려주는 함수
signal 함수
임계 구역 앞에서 기다리는 프로세스에게 들어가도 된다는 신호를 주는 함수
임계 구역에 갈 수 있는지 기다려야하는지 알려주는 함수
이다.wait() { while(S <= 0){ // 사용할 자원이 없으면 0 이다. // 사용할 자원이 있는지 반복적으로 확인 } S--; }
임계 구역 앞에서 기다리는 프로세스에게
들어가도 된다는 신호를 주는 함수
이다.signal() { S++; }
작성 중
뮤텍스 락과 마찬가지로
사용할 수 없는 자원이 없으면 반복적으로 확인
한다.이러한 작업은
CPU 를 낭비
한다.그러나
카운팅 세마포의 wait 함수
에서는 사용할 수 있는 자원이 없는 경우
해당 프로세스를waiting(또는 Blocking) 상태
로 만들고
프로세스의PCB
를세마포를 위한 대기 큐
에 넣는다.그리고 다른 프로세스가 임계 구역에서 작업이 끝나고
signal 함수를 호출
하면
대기 큐에 있던 프로세스
를ready 상태
로 만들고ready queue
에 넣는다.
카운팅 세마포와 비슷하지만
전역 변수 S 값을0
과1
만 가지는 세마포
S 가 0이면 잠겨있는 것이고, 1이면 잠금이 해제된 것카운팅 세마포와 마찬가지로
wait() 과 signal() 을 사용
하여
신호 전달 메커니즘
을 사용해서 잠금을 구현함현재 스레드보다 우선순위가 높은 쓰레드가 잠금을 해제하고 잠글 수 있다.
선점 가능
이러한 이유로공유자원에 대한 소유권이 없고
잠금/해제 권한이 여러 프로세스에게 있기 때문에 뮤텍스 락 보다 속도가 빠르다.
세마포에서 임계 구역 앞뒤로
wait과 signal 함수
를 매번 명시하는 것은 번거롭다.또한 순서 변경 혹은 앞뒤로 같은 함수를 명시하는
예기치 못한 실수
가 발생할 수 있다.
이러한 불편함을 해소하고자 나온 메커니즘이 모니터이다.
모니터는
공유 자원
과공유 자원에 접근하기 위한 인터페이스
를 묶어 관리한다.프로세스는
반드시 인터페이스를 통해서만 공유 자원에 접근
하도록 한다.
이를 위해서모니터
를 통해공유 자원에 접근하고자하는 프로세스를 큐에 삽입
하고
삽입한 순서대로 하나씩 공유자원을 이용
하도록 한다.즉 모니터 안에 항상 하나의 프로세스만 들어오게 되어
상호 베제를 위한 동기화를 제공
한다.
모니터는 실행 순서 제를 위한 동기화도 제공한다.
특정 조건을 바탕으로 프로세스를 실행하고 일시 중단하기 위해 조건 변수를 사용한다.조건 변수란 프로세스나 실행 순서를 제어하기위해 사용하는 특별한 변수이다.
이 조건 변수에는 wait() 에 의해서 waiting 상태가 된 프로세스를 저장하는 큐가 할당되어있다.
wait() 연산으로 큐에 들어간 프로세스
는
signal() 에 의해서 모니터의 인터페이스로 이동
할 수 있다.
따라서
signal()
에 의해서 모니터 인터페이스로 이동한 프로세스는
signal()을 호출한 프로세스가 모니터를 떠난뒤에 실행
되거나
signal()을 호출한 프로세스의 실행을 일시 중단하고
자신이 실행된 뒤 다시 signal()을 호출한 프로세스를 재개한다.`