티스토리 뷰
동시에 실행되는 프로세스들이 만약 하나의 자원에 대해 동시에 접근했다고 생각해보자.
그럼 하는 읽고, 하나는 쓰며, 하나는 수정하고 ..여러 작업을 동시에 한뒤 각자, 동.시.에. 저장을 하게된다면?
A : 나는..남김이..야..
B : 나는.. 똥..변비가.. 있어.. 막무가내로 동시에 저장을 하게 된다면..?
C : 아.. 집에 있는 고양이.. 보고 싶다.. ------------------------------------> 나는 집에 있는 똥이 보고싶어.
D : 운영체제..좋아..
이런 말도 안되는 기록이 될 수도 있다.
말을 너무 어렵게 한 부분이 있다고 생각한다.
다시금 쉽게 얘기하자면!!!
동시다발적으로 실행되는 프로세스들은 공통의 목적을 올바르게 수행하기 위해 서로 협력하며 영향을 주고 받기도한다.
이렇게 협력하여 실행되는 프로세스들은 실행 순서와 자원의 일관성을 보장해야하기 때문에 동기화가 필요하다.
동기화란?
특정 자원에 접근할 때 한 개의 프로세스만 접근하게 하거나, 프로세스를 올바른 순서대로 실행하게 하는 것을 의미한다.
즉, 동기화에는 실행 순서 제어를 위한 동기화가 있고 상호 배제를 위한 동기화가 있다.
실행 순서 제어를 위한 동기화
Read, Writer의 예시로, 두 프로세스가 각각 Read, Writer을 실행한다고 보자. 쓰는 프로세스가 문서에 작성을 해야 읽는 프로세스는 해당 문서를 읽을 수 있는데 읽는 프로세스가 쓰기도 전에 먼저 읽게되면 문서의 아무 내용도 못읽게 된다.
이렇듯, 읽고 쓰는 프로세스는 쓰고 있는 것에 대한 확인을 위한 하나의 동작을 유연하게끔 자원을 공유해야하는데 순서가 제대로 되지 않는다면 문제가 발생하게 된다 .
상호배제를 위한 동기화
공유가 불가능한 자원을 동시 사용을 피하기 위한 알고리즘이다.
A가 입금, B가 출금 후 입금을 하게되는 과정을 살펴보자
0원의 계좌에서 A가 200원을 입금 후 100원을 출금 하면 계좌는 100원이 되고,
B가 해당 계좌에 100원을 출금 후 300원을 입금하게되면 총 300원이 남게된다.
그러나 동일한 자원인 계좌에 동시에 사용하게 되면 어떻게 될까?
1000원의 계좌에 A가 200원을 입금 후 B가 100원을 출금하게 되었을 떄
A의 입장에서는 1200원으로 찍히고 있는 상황,
B의 입자에서는 900원으로 찍히고 있는 상황,
여기서 추가적으로 A가 100원을 출금, B가 300원을 입금하게되면?
A의 입장에서는 1100원으로 찍히게되고
B의 입장에서는 1200원으로 찍히게된다.
A가 결과값 1100원을 저장한 뒤에
B가 결과값 1200원을 저장하게 되면
동시다발적으로 일어난 이 행위에 대한 결과값은 마지막으로 저장한 B의 결과값 1200원이 저장되게 된다.
A의 행위가 계좌에 적히지 않게 된 것이다.
이것은 하나의 자원인 계좌에 동시 다발적으로 일어난 A,B의 작업에 대해
자원의 올바른 일관성을 지키지 못한 사례다.
(다른 대표적인 예시로는 생산자와 소비자 문제가 있다.)
임계구역이란?
위의 계좌와 같이 계좌는 공유자원이기도 하며 이러한 공유 자원은 전역변수가 될수도 있으며, 파일, 입출력장칭, 보조 기억장치가 될 수도 있다. 그러나 위의 계좌에서 "잔액"이라는 변수는 동시에 실행하면 문제가 생기는 자원으로써, 이런 자원에 접근하는 코드 영역을 임계 구역이라고 한다,
임계 구역에 두 개 이상의 프로세스가 동시에 실행되면 안되지만 , 동시에 실행되어 생기는 문제를 레이스 컨디션(race condition)이라고 한다.
임계 구역 문제 세가지 원칙
운영체제는 이러한 임계 구역 문제를 세가지 원칙하에 해결해야하는데 그 원칙은 이러하다.
상호배제(mutual exclusion) : 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 임계 구역에 들어올 수 없다.
진행(progress) : 임계 구역에 어떤 프로세스도 진입하지 않았다면 임계 구역에 진입하고자 하는 프로세스는 들어갈 수 있다.
유한대기 (bounded waiting) : 한 프로세스가 임계 구역에 진입하고 싶다면 그 프로세스는 언젠가 들어갈 수 있다.(무한정 기다림 x)
위를 통해 우리는 동기화하지 않을 경우 생길 수있는 문제상황을 파악했고, 동기화란 무엇인가와 임계구역, 공유 자원에 대해 알아봤다. 그럼 다음으로 어떻게 동기화가 이루어지는 지에 대해 알아보자
대표적인 동기화 도구는 뮤텍스 락, 세마포, 모니터가 있다.
뮤텍스 락(mutex lock) 이란?
뮤텍스 락을 설명하기 위해서는 화장실을 예시로 들 수 있다.
화장실에 단 한명의 인원만을 수용할 수 있다고 생각해보자.(양변기가 하나뿐이란다 ㅋ)
그럼 화장실이라는 임계구역을 들어가기 위해 기다리는 사람은 프로세스가 된다.
프로세스 임계구역
( A) (B) (C) --------- 화장실
" 아 빨리 싸!!"
여기서 중요한 점은 화장실을 사용하는 프로세스는 화장실 문을 자물쇠로 걸어 자신이 사용중이기에 타인이 들어오지 못 하도록 한다. 이러한 자물쇠 기능을 코드로 구현한 것이 뮤텍스 락이다.
임계구역에 진입하려는 프로세스는 현재 내가 임계구역에 있음을 알리기 위해 뮤텍스락을 통해 자물쇠를 걸어두고 사용을 다했다면 임계구역에 나왔음을 알리기 위해 자물쇠를 풀 수 있는 형식이다.
자물쇠 - 프로세스들이 공유하는 전역변수 lock
임계구역을 잠구는 함수 acquire (해당 자원을 얻는다! 라는 의미)
임계구역을 잠금 해제하는 역할 release(프로세스가 갖고있던 자원을 해방시킨다! 라는 의미)
이러한 방법을 코드로 보면 아래와 같이 이해할 수 있다 .
'synchronization variable'
boolean lock = false;
acquire(){
while(lock){
/*
>> "Busy Waiting"
*/
}
lock = true;
}
release(){
lock = false;
}
while(true){
acquire lock
"Critical Section"
release lock
"Remainder Section"
}
세마포(semapore)란?
세마포는 뮤텍스락과 비슷하지만 좀 더 일반화된 방식의 동기화 도구다.
이전의 뮤텍스락은 하나의 공유자원에 접근하는 방식이었다면, 세마포는 여러개가 존재하는 공유자원을 동기화하기 위한 도구다.
(엄밀히 말하면 이진 세마포, 카운팅 세마포가 있지만 이진 세마포의 경우, 뮤텍스락과 매우 비슷하므로 여러 공유 자원을 다루는 카운팅 세마포를 다룬다. )
위에서 다룬 코드를 보면 뮤텍스 락의 경우
변수 lock에 대한 false, true 값을 통해 자원에 접근하는 것을 볼 수 있다.
그러나 세마포는 여러 자원에 대한 접근을 다루기 때문에 , false true 두 개의 값에 대한 접근이 아닌
접근 가능한 자원의 개수에 따라 접근이 가능하도록 설계된다.
아래 코드를 보고 이해해보자.
'Synchronization variable'
Semaphore S = N // Unsigned Integer
wait(S){
while(S <= 0){
/*
"Busy Waiting"
*/
}
S--;
}
signal(S){
S++;
}
wait()을 통해 S 변수에 담긴 자원의 개수가 생길 때까지 기다리게 된다.
이후 할당 받게되면 자원의 개수 s를 --뺴주고 다 사용하게 될 경우,
signal()을 통해 자원을 release(s++) 해준 뒤,
다른 프로세스가 사용할 수 있도록 wakeup()함수를 통해 기다리고 있는 프로세스를 깨워준다.
모니터(monitor)란?
세마포 또한 매우 훌룡한 프로세스 동기화 도구지만, 조금 불편한 경우가 있다. 위에 설명과 같이 wait(),signal(),wakeup()등 다양한 함수를 앞뒤로 일일이 명시해야하는 번거로운 작업이 있다.
또한 코드가 방대해지고 복잡해지면 위와같은 작업은 실수를 낳을 수 있다.
이에 대해 해결 방법으로 나온 최신 동기화 도구가 모니터다.
사용자가 사용하기에 훨씬 편리한데, 공유자원과 공유 자원에 접근하기 위한 인터페이스를 묶어 관리한다.
즉, 프로세스는 공유자원을 사용하기위해 반드시 인터페이스를 통과 하도록 설계하는 것인데,
인터페이스 이전에 큐 형식으로 프로세스의 줄을 세우고 삽입된 순서대로 하나씩 공유자원에 접근하도록 한다.
위 그림에서는 lock 과 wait이 존재하는 이게 무엇인가?
바로 특정 조건을 바탕으로 프로세스를 실시하고 중단 시키는 조건 변수를 사용하고 있는 것이다.
wait()을 호출한 프로세스는 상태를 대기로 전환하고 일시적으로 조건 변수에 대한 대기 큐에 삽입 후,
해당 조건을 충족 시킬 변수에 대해 signal() 함수를 만나게 되면 ,
다시 공유 자원에 접근하게 되어 사용하게 된다.
응? 이게 무슨 소리야 하고 갑자기 당황스러울 수 있다.
우리는 이전에 프로세스가 CPU를 빠른 속도로 할당 받을 수 있다고 배웠다.
각 프로세스에 대해 CPU가 쉬고 일하고 쉬고 일하고 빠른 속도로 반복하게되는데
이러한 메커니즘은 동기화에 있어서 영향을 미친다.
그렇기 때문에 wait과 signal을 통해 관리되며, 동기화에서 문제가 일어나지 않도록 하는 것이다.
그림참고)
https://tecoble.techcourse.co.kr/post/2021-10-23-java-synchronize/
'Operating System' 카테고리의 다른 글
6. Deadlock (0) | 2023.01.19 |
---|---|
4. CPU Scheduling (0) | 2023.01.19 |
3. Thread (0) | 2023.01.16 |
2. Process (0) | 2023.01.15 |
1. Operating System (0) | 2023.01.15 |