컴퓨터과학/운영체제

[운영체제] 유저 모드의 동기화 vs 커널 모드의 동기화

PureStack 2021. 11. 30. 20:24

유저 모드의 동기화

임계 구역 기반의 동기화(Critical Section)

  • 열쇠를 억은 프로세스만 임계 구역에 들어갈 수 있다. 즉, 한번에 하나의 스레드만 접근 가능하다.
  • 임계 구역 진입을 위한 크리티컬 세션 오브젝트를 얻는다.
  • 특정 스레드가 열쇠를 가지고 있으면, 그 스레드가 반환할 때까지 임계 구역은 blocking된다. 열쇠가 반환되면 임계 구역은 blocking 상태에서 벗어나게 되어 다른 스레드는 열쇠를 얻고 임계구역에 접근할 수 있다.

인터락 함수 기반의 동기화(Interlock)

  • 함수 내부적으로 한 순간에 하나의 스레드에 의해서만 실행되도록 동기화된다.
  • 임계 구역 기반의 동기화도 내부적으로 인터락 함수를 기반으로 구현된다.
  • 유저 모드 기반으로 동작하여 속도가 빠르다.

커널 모드의 동기화

뮤텍스(Mutex)

  • 공유된 자원의 데이터를 여러 프로세스, 스레드가 접근하는 것을 막는 것이다.
  • 임계 구역을 가진 스레드들의 Running time이 서로 겹치지 않게 단독으로 실행하게 하는 기술이다.
  • 뮤텍스 객체를 두개 이상의 스레드가 동시에 사용할 수 없다.
  • 일종의 Lock 매커니즘으로 공유 자원에 대한 접근을 조율하기 위해 lock과 unlock을 사용한다.
  • Lock에 대한 소유권이 있으면서 Lock을 가지고 있을 경우에만 임계 구역에 진입 가능하고, Lock을 가진 스레드만 반납할 수 있다.
  • 뮤텍스는 무조건 1개의 열쇠만 있다. 이를 테면, 화장실 칸이 1개밖에 없는 상황에서 열쇠를 가진 사람만이 화장실에 갈 수 있고, 다음 사람이 화장실에 가기 위해서는 앞 사람이 열쇠를 반납해야 한다.
key = 1;

void lock() {
    while(key != 1){} // key의 값이 1이 될 때까지 기다린다.

    // 이 구역에 도착한 것은 key의 값이 1이라는 의미이다.
    key = 0; // key 값을 1로 만들어 다른 프로세스나 스레드가 접근하지 못하도록 막는다.
}

void unlock() {
    key = 1; /* 임계 구역에서 나온 프로세스나 스레드는 다른 프로세스나 스레드들이 접근 가능하도록 key를 반납한다.
                다시 말해 lock을 해제한다. */
}

세마포어(Semaphore)

  • 공유된 자원의 데이터를 여러 프로세스, 스레드가 접근하는 것을 막는 기법이다.
  • 동시에 접근할 수 있는 허용 가능한 갯수를 가지고 있는 Counter라는 변수가 있다.
  • Counter는 공유자원에 접근할 수 있는 프로세스 혹은 스레드의 수를 나타내는 값으로, 공동으로 관리하는 하나의 값이다.
  • 예를 들어, 화장실이 있고 화장실 칸이 4개가 있으며 열쇠 역시 4개라면, 4명까지는 대기없이 바로 사용 가능하고, 그 다음부터는 대기를 해야 ㅎ나다.
  • 여기서 세마포어 Counter의 개수가 1개일 때는 Binary Semaphore, 즉 뮤텍스이며 2개 이상일 때는 Counting Semaphore이다.
  • 세마포어는 소유할 수 없다. 세마포어를 소유하지 않은 스레드가 세마포어를 해제할 수 있는 문제가 발생할 수 있기 때문이다.
struct semaphore{
    int cnt;
    Queue queue;
};

/* wait 연산: 세마포어의 값을 감소시키며, 값이 음수가 되면 wait를 호출한 프로세스나 스레드는 Block된다.
음수가 아니면, 프로세스는 계속 수행한다. */
void wait(semaphore s) {

    s.count--;

    if(s.count < 0) {
        // 이 구역은 프로세스나 스레드가 공유 자원에 접근할 수 없는 상태임을 의미한다.
        // 요청한 프로세스를 s.queue에 연결 시키고, Block 상태로 전이 시킨다.
    }
}

/* signal 연산: 세마포어의 값을 증가시키며, 만약 값이 양수가 아니면 wait 연산에 의해 Block된 
프로세스나 스레드들을 깨운다. */
void signal(semaphore s) {

    s.count++;

    if(s.count <= 0) {
        // count가 0보다 작거나 같은 상태는 대기하고 있는 프로세스나 스레드가 존재함을 의미한다.
        // s.queue에 연결되어 있는 프로세스나 스레드를 큐에서 제거한다.
        // 프로세스나 스레드 상태를 실행 가능으로 전이시키고 ready list에 연결시킨다.
    }
}

이를 활용하면 다음과 같다.

int n = 4; //스레드의 개수는 4개
semaphore s = 1;

void start(int m) {
        while(true) {
            wait(s);

            //임계 구역

            signal(s);

            //임계 구역 이후 코드
        }
}

void main() {
        begin ( start(1), start(2), start(3), start(4) );
}

모니터(Monitor)

  • 하나의 프로세스 내에서 다른 스레드 간의 동기화에 사용된다.
  • Mutex(Lock)과 Condition Variables를 가지고 있는 동기화 매커니즘이다.
  • 모니터는 프레임워크나 라이브러리 그 자체에서 제공되며, C언어에는 없고 Java에서 제공된다.
  • synchronized, wait(), notify() 등의 키워드들을 통해 더 편하게 동기화가 가능하다.

 

 

참고자료

https://wannabe-gosu.tistory.com/27

 

[운영체제] 뮤텍스(Mutex), 세마포어(Semaphore) 그리고 모니터(Monitor)

이 셋은 모두 운영체제의 동기화 기법이다. 일단 뮤텍스와 세마포어부터 살펴보자. 운영체제에선 공유된 자원에 대해 여러 프로세스, 쓰레드가 접근하여 문제가 발생하는 것을 방지하고자 운영

wannabe-gosu.tistory.com

 

https://velog.io/@conatuseus/OS-%EC%84%B8%EB%A7%88%ED%8F%AC%EC%96%B4%EC%99%80-%EB%AE%A4%ED%85%8D%EC%8A%A4

 

[OS] 세마포어와 뮤텍스

세마포어와 뮤텍스은"여러 프로세스나 쓰레드가 공유 자원에 접근하는 것을 제어하기 위한 방법"으로 정의할 수 있습니다. 즉, 병행 처리를 위한 프로세스 동기화 기법입니다. 예를 들자면 교차

velog.io