[OS]Day6

프로세스 동기화

여러 개의 프로세스가 데이터를 공유할 때 무결성을 유지해야한다.

 

예를 들어 P1과 P2가 공유 데이터를 사용할 때 아래와 같은 명령을 번씩 실행한다면, +1 -1이기 때문에 count의 값은 변화가 없어야한다. 하지만 count의 초기값이 0이라고 가정했을 때, P1과 P2가 count가 0일 때 동시에 접근한다면?

3번 라인이 실행될 때 count는 1이 됐다가 P2에 의해 -1이 될 수 있다. 1번씩 실행됐음에도 실행 결과가 바뀌었다.

동기화란 멀티 프로세싱에서 이와 같은 문제를 해결하기 위해 동시에 여러 프로세스가 접근해야하는 공유 데이터를 동시가 아닌 순차적으로 접근하도록 만드는 방법이다.

 

Race Condition

여러 개의 프로세스에서 동시에 같은 데이터에 접근하려고 하는 상황을 말한다.

위 예제에서는 count에 동시 접근하기 때문에 Race Condition이다.

 

Critical section (임계 영역)

여러 프로세스가 동시에 접근하는 영역으로, 위 예제가 Critical section이다.

 

Critical Section Problem Solution

요구 조건

  1. Mutual Exclusion(상호 배제)
    • 어떤 프로세스가 Critical section에 접근 중일 때 다른 프로세스는 접근할 수 없다.
  2. Progress(avoid deadlock)
    • DeadLock: Critical Section에 접근하기 위해 다른 프로세스들이 기다리고 있는 상황이 무한정 이어지는 상황
  3. Bounded Waiting(avoid Starvation)
    • Critical section에 진입을 할 때도 스케줄링 처럼 우선순위를 통해 진입한다. 이때 starvation 상태가 되어서는 안된다.
    • starvation을 해결하기 위해 대기시간에 제한을 두어야한다.

 

해결 방법

Mutex Locks

Mutual Exclusion을 보장하는 방법으로 Critical Section에 프로세스가 진입하면 Critical Section을 Lock하고 빠져나올 때 unlock하는 방식으로 하나의 프로세스만이 자원을 선점할 수 있다.

while (true) {
    //acquire lock
    
    //...critical section
    
    //release lock
    
    //...remainder section
}

acquire(), release()는 atomic하게 만들어야한다.

Busy Waiting: while이 계속 true로 돌면서 release가 됐는지 확인하고 있기 때문에 리소스가 낭비된다.

이런 locking 방식을 Spinlock이라고 하며, 코어가 여러 개이고, CPU가 놀고있는 상황이라면 괜찮은 방식이다.

 

Semaphore

뮤텍스 락이 잠금 방식이었다면, 세마포어는 신호를 주는 방식이다. 

wait(), signal()를 사용하는데 뮤텍스의 acquire()과 release()와 비슷하지만, true false가 아닌 숫자를 사용해서 여러 개의 프로세스가 자원을 선점할 수 있다.

원하는 수 만큼 S를 주고, S가 0이 되면 접근할 수 없게 한다. => s를 1로 주면 0,1 밖에 안되기 때문에 뮤텍스와 같다. 

Mutex는 소유하고 있는 스레드만이 이 Mutex를 해제할 수 있는 반면, Semaphore Semaphore를 소유하지 않는 스레드가 Semaphore를 해제할 수 있다.

세마포어에서는 Busy waiting을 해결하기 위해 sleep(), wakeUp()을 사용해서 대기 중인 프로세스를 Waiting queue에 넣고, 실행될 때 Ready queue에 넣어준다.

 

Monitors

semaphore, mutex에서 wait와 signal의 순서가 바뀌면, lock이 제대로 걸리지 않는다.

이런 일이 잘 일어나지 않지만 코드를 짜다보면 이런 일이 발생할 수 있다.

모니터 타입의 클래스를 선언하고 모니터 내부에서 함수를 실행하면, 동기화된 함수로써 사용이 가능하다.

추가적으로 condition 변수를 주어 작업에 대해 락을 분리할 수 있다.

x 조건을 가진 작업들의 entry queue로 분리해서 x의 프로세스를 깨울 때 x.signal(), x.wait()을 통해 작업이 가능하다.

'개념 정리 > OS' 카테고리의 다른 글

[OS] Day8  (0) 2023.08.21
[OS] Day7  (0) 2023.08.18
[OS]Day5  (0) 2023.08.14
[OS]Day4  (0) 2023.08.10
[OS] Day3  (0) 2023.08.09