본문 바로가기
학교 강의/운영체제

프로세스 동기화

by hoshi03 2024. 7. 9.

동기화 : 프로세스들의 실행 순서를 맞추기, 실행 순서를 제어하기 위한 동기화와 상호 배제를 위한 동기화가 있다

 

• 실행 순서 제어를 위한 동기화

READER, WRITER가 있을때 READER는 WRITER가 값을 갱신한 후에 읽어와야 올바른 값을 가져올 수 있다

 

• 상호 배제를 위한 동기화

 

- 생산자와 소비자 문제

#include <iostream>
#include <queue>
#include <thread>

void produce();
void consume();

//std::queue<int> q;
int sum = 0;

int main() {

    std::cout << "초기 합계: " <<  sum << std::endl;
    std::thread producer(produce);
    std::thread consumer(consume);

    producer.join();
    consumer.join();

    std::cout << "producer, consumer 스레드 실행 이후 합계: " <<  sum << std::endl;

    return 0;
}

void produce() {
    for(int i = 0; i < 100000; i++) {
        // q.push(1);
        sum++;
    }
}

void consume() {
    for(int i = 0; i < 100000; i++) {
        // q.pop();
        sum--;
    }
}

 

상호 배제가 이루어지지 않은 환경에서는 프로세스가 동기화되지 않아 둘다 실행한 후에 초기 값이 유지되지 않는다

공유 자원에 접근하는 임계구역에 여러개의 프로세스가 진입하고자 하면 한 프로세스가 작업하는 동안 다른 프로세스는 대기하게 해주어야 한다

 

위의 예제는 동시다발적으로 임계 구역의 코드를 실행해서 레이스 컨디션이 발생한 경우..

 

sum++ 이나 sum-- 등의 작업을 할때

저 코드 한줄만 실행되는게 아닌 

레지스터에 현재 sum 변수값을 저장하고, 레지스터의 값을 증가시키고, 다시 sum 변수에 레지스터의 값을 저장하는 과정을 거치게 되는데 이 과정 중간에 컨텍스트 스위칭이 발생해서 문제가 생기는 것

 

이러한 임계 구역 문제를 해결하기 위해서 3가지 원칙을 지켜야 한다

1. 상호 배제 mutuak exclusion : 한 프로세스가 임계 구역에 진입했을때 다른 프로세스는 임계 구역 진입 불가

2. 진행 progress: 임계 구역에 진입한 프로세스가 없다면 임계 구역에 진입하고자 하는 프로세스는 들어갈 수 있어야 한다

3. 유한 대기 bounded waiting: 어떤 프로세스가 임계 구역에 진입할 수 있다면 언젠가 임계 구역에 들어올 수 있어야 한다

 

• 동기화 기법

 

동기화를 통해 임계구역에 한 프로세스만 진입하게 하고 실행순서를 보장하는 방법 3가지

 

- 뮤텍스 락

 

프로세스가 임계 구역에 진입하면 lock을 걸고, lock이 걸려있지 않으면 임계 구역에 진입하는 형태

lock 전역변수, 락을 거는 acquire 함수, 락을 해제하는 release 함수로 뮤텍스 락 구현 가능

물론 언어에서 제공하는 뮤텍스 락 기능이 있고, 위처럼 간단하게 구현되지 않았음

 

세마포어

 

세마포어는 공유자원이 여러개 있을 때 여러 프로세스가 각각 공유 자원에 접근하게 하는 방법

뮤텍스 락과 비슷하게 비슷하게 구성되고

 

임계구역에 진입할수 있는 프로세스 갯수가 0개 이하면 무한루프를 돌면서 사용할 수 있는 자원이 있는지 확인하고

진입할수 있으면  s를 1 감소시키고 임계구역에 진입한다

wait (){
while ( s <= 0)
    ;
    s--;
}

 

임계구역에서의 작업을 마치면 signal()함수로 s++를 해서 다른 함수가 진입 가능하게 한다

 

위의 방법을 사용하면 임계 구역 문제를 해결할 수 있지만 계속 무한루프를 돌면서 대기를 해야되기에

위의 방법 대신 임계 구역에 진입하려는 프로세스를 대기 상태로 만들고, PCB를 대기 큐에 집어넣는 방식으로 구현한다

 

wait 메서드에서는 s<0 일때 프로세스를 대기 큐에 넣고 sleep() 메서드를 호출해서 대기시키고

signal 메서드에서는 큐에서 프로세스 하나를 꺼내와서 wakeUp 메서드로 준비 상태로 만든다

 

모니터

 

세마포의 wait과 signal 함수를 명시하는 것 보다 편리한 동기화 도구

모니터는 공유자원과 공유 자원 접근 인터페이스를 묶어서 관리한다

프로세스는 인터페이스를 통해서만 공유 자원에 접근할 수 있다

 

모니터를 통해 공유 자원에 접근하고자 하는 프로세스를 큐에 삽입하고, 큐에 삽입된 순서대로 하나씩 공유 자원을 이용

모니터에서 프로세스의 실행 순서를 제어하기 위해 조건 변수로 wait과 signal 연산을 수행한다

모니터에 진입하기 위한 큐와 wait로 실행 중단된 프로세스들이 들어가는 큐는 다르다!

모니터 안의 프로세스가 wait를 통해서 조건 변수 큐에 들어가면 다른 프로세스가 모니터 안에 들어올 수 있고

다른 프로세스의 signal을 통해 실행을 재개할 수 있다

 

모니터 안에는 하나의 프로세스만 들어올 수 있기에

wait를 호출한 프로세스는 signal을 호출한 프로세스를 중단하고 실행되거나 signal을 호출한 프로세스가 실행이 끝난 뒤에 호출된다

 

자바에서 사용하던 synchronized 키워드가 모니터를 이용해서 동작되는 것이라고 한다

 

'학교 강의 > 운영체제' 카테고리의 다른 글

메모리 할당 & 페이징  (0) 2024.07.10
교착상태  (0) 2024.07.10
CPU 스케줄링  (1) 2024.07.09
스레드  (0) 2024.07.09
프로세스  (0) 2024.07.04