[CS] 동기화 기법

정은아·2024년 2월 2일
post-thumbnail

💡 프로세스를 동기화하지 않으면 겉보기에 아무런 문제 없어 보이는 코드도 예끼치 못하게 작동할 수 있다. 동기화를 위한 대표적인 도구인 뮤텍스락, 세마포, 모니터에 대해 알아보자

뮤텍스 락(Mutex lock: MUTual EXclusion lock)

  • 상호배제를 위한 동기화 도구로 동시에 접근하면 안되는 자원에 프로세스이다. 스레드의 동시접근을 막는다.
  • 임계구역이 비었을 때 임계구역에 진입하는 프로세스는 뮤텍스 락을 이용해 임계구역에 자물쇠를 걸어둔다.
  • 다른 프로세스는 임계구역이 잠겨 있으면 기다리고, 비게 되면 뮤텍스 락을 걸고 임계구역에 진입한다.

뮤텍스 락의 구현

  • 하나의 전역 변수와 2개의 함수로 구현된다.
  • 임계구역의 자물쇠 역할로 프로세스들이 공유하는 전역 변수 lock
  • 임계구역을 잠그는 함수 acquire
  • 임계구역의 잠금을 해제하는 함수 release

acquire 함수

  • 프로세스가 임계구역에 진입 전 호출한다.
  • 임계 구역이 잠겨 있으면 열릴 때 까지(lock이 false가 될 때 까지) 임계 구역을 반복적으로 확인한다.
  • 임계 구역이 열려 있으면 임계 구역을 잠근다(lock을 true로 바꾼다).

release 함수

  • 프로세스가 임계 구역에서 작업을 끝내고 호출하는 함수이다.
  • 잠긴 임계 구역을 열어주는 함수 (lock을 false로 바꾼다.)
acquire() {
    while (lock == true)		// 만약 임계 구역이 잠겨 있다면 
        ;				       // 임계 구역이 잠겨 있는지를 반복적으로 확인 
    lock = ture;			  // 만약 임계 구역이 잠겨 있지 않으면 임계 구역을 잠금
}

release() {
    lock = false;			// 임계 구역 작업이 끝났으니 잠금 해제
}
  • acquire와 release함수를 아래와 같이 임계 구역 전후로 호출함으로써 하나의 프로세스만 임계 구역에 진입할 수 있다.
acquire();	// 자물쇠 잠겨 있는지 확인, 잠겨 있지 않으면 잠그고 들어가기
// 임계 구역	// 임계 구역에서의 작업 진행
release();	// 자물쇠 반환
  • 앞서 언급했던 생산자 소비자 문제를 아래와 같이 뮤텍스로 구현한다면?
acquire();
// '총합' 변수 접근
release();

뮤텍스 락 정리

  • 락을 획득할 수 없으면 (임계 구역 진입할 수 없다면) 무작정 기다린다.
  • 락을 획득할 수 있으면 (임계 구역 진입할 수 있다면) 임계 구역을 잠근 뒤 임계 구역에서 작업을 진행한다.
  • 임계 구역을 빠져 나올 땐 임계 구역 잠금을 해제한다.
  • 위의 과정을 실행함으로써 임계구역을 보호할 수 있다.
while(lock == true)     // 만약 임계 구역이 잠겨 있다면
        ;               // 임계 구역이 잠겨 있는지를 반복적으로 확인
  • 반복적으로 상태가 변경되었는지 확인하며 대기하는 방식을 바쁜 대기(busy wait)라고 한다.

뮤텍스 락의 한계

  • 사용할 수 있는 공유 자원이 없으면 프로세스는 무한히 반복하며 공유 자원 사용 가능 여부를 확인해야 한다.
  • 즉, 바쁜 대기 상태로 CPU의 주기를 낭비하게 된다.

세마포(semaphore)

  • 뮤텍스 락보다 조금 더 일반화된 동기화 도구
  • 공유 자원이 여러 개 있는 상황에서도 적용이 가능하다.
  • 철도 신호기에서 세마포란 단어가 유래되었다.

세마포의 종류

  • 세마포의 종류에는 이진 세마포와 카운팅 세마포가 있다.
    • 이진 세마포(binary semaphore): 뮤텍스 락과 비슷한 개념. 공유 자원이 하나를 말한다.
    • 카운팅 세마포(counting semaphore): 공유 자원이 여러 개일 때를 뜻한다.

세마포의 구현

  • 하나의 전역 변수와 두개의 함수로 구현된다.
    • 임계 구역 진입 가능 프로세스 개수 (사용 가능 공유 자원 개수)를 나타내는 전역 변수 S
    • 임계 구역에 들어가도 좋은지, 기다려야 하는지를 확인하는 wait 함수
    • 임계 구역에서 기다리는 프로세스에 진입이 가능하다고 신호를 주는 signal 함수
wait()
// 임계구역
signal()
# wait 함수
wait () {
    while (S <= 0 )	// 1
    	;	     	// 2
    S--;	    	// 3
}

- 1 : 임계 구역에 진입할 수 있는 프로세스 개수가 0개 이하라면
- 2 : 사용할 수 있는 자원이 있는지를 반복 확인
- 3 : 임계 구역 진입 가능 프로세스가 1개 이상이면 S를 1 감소시키고 임계구역 진입
  • signal 함수는 다음과 같이 만든다.
# signal 함수
signal () {
    S++		// 1 
}

- 1 : 임계 구역에서 작업을 마친 후 S를 1 증가 시킨다.
wait()
// 임계 구역
signal()

세마포의 대기 극복

  • 세마포는 wait 함수에서 사용 가능 자원이 없을 때 프로세스를 대기상태로 만들어 바쁜 대기를 방지한다.
  • 프로세스의 PCB를 대기 큐에 집어넣고, signal 함수 호출을 대기한다.
  • 다른 프로세스가 임계 구역 작업이 끝나고 signal 함수를 호출하면, signal 함수는 대기 중인 프로세스를 대기 큐에서 제거한다.
  • 대기 큐에서 제거된 프로세스는 준비 상태로 변경되고 준비 큐로 이동된다.
# 변경된 wait 함수
wait () {
    S--;
    if ( S < 0 ) {
        add process p to Queue;  // 1. 해당 프로세스 PCB를 대기큐에 삽입한다. 
        sleep();                 // 2. 대기 상태로 접어든다
    }
}


# 변경된 signal 함수
signal () {
    S++
    if (S <= 0 ) {
        remove a process p from Queue // 1. 대기 큐에 있는 프로세스 p 제거한다.
        wakeup(p)                     // 2. 프로세스 p를 대기 상태에서 준비 상태로 만든다.
    }
}

모니터(monitor)

  • 세마포에 비하면 사용자가 사용하기에 훨씬 편리한 도구이다.
  • 공유 자원과 공유 자원에 접근하는 인터페이스(통로)를 묶어서 관리한다.
  • 프로세스는 반드시 인터페이스를 통해서만 공유 자원에 접근한다.
  • 인터페이스에 접근할 프로세스는 큐(모니터에 진입하기 위한 큐)에 삽입되고, 모니터 내에는 항상 하나의 프로세스만 들어오도록 하여 상호배제를 위한 동기화를 실현한다.
  • 조건 변수를 통해 특정 조건을 바탕으로 프로세스 실행 및 일시 중단하여 실행 순서를 위한 동기화를 실현한다.
    • 프로세스나 스레드 실행 순서를 제어할 때 사용하는 변수를 조건 변수(conditional variable)라고 한다.

모니터의 조건 변수

  • 모니터가 조건 변수를 사용한다고 하지만, 조건변수와 모니터는 별개의 개념이다.
  • 조건 변수는 waitsignal 연산을 수행할 수 있다.
    • wait는 호출한 프로세스 상태를 대기 상태로 전환하고 일시적으로 조건 변수에 대한 대기 큐에 삽입하는 연산이다.

      💡 상호 배제를 위한 큐와 조건 변수에 대한 대기 큐는 다르다.

      • 전자는 모니터에 한 번에 하나의 프로세스만 진입하도록 만들어진 큐이고, 후자는 모니터에 이미 진입한 프로세스의 실행 조건이 만족될 때 까지 잠시 실행이 중단되어 기다리기 위해 만들어진 큐이다.
  • 조건변수는 여러가지가 있을 수 있다.
    • ex) 특정 프로세스가 모니터에 들어오고 x.wait()가 호출되면 조건 변수 x가 만족할 때까지 대기한다.
  • wait 연산으로 실행이 일시 중지된 프로세스는 다른 프로세스의 signal 연산을 통해 실행이 재개될 수 있다.
    • ex) x.signal은 조건변수 x 대기 큐에 삽입된 프로세스 실행을 재개하는 함수이다.

모니터에서 프로세스의 실행 조건

  • wait을 호출했던 프로세스는 signal을 호출한 프로세스가 모니터를 떠난 뒤 실행될 수 있다.
  • signal을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal을 호출한 프로세스의 수행을 재개한다.

    💡 중요한 점은 모니터는 조건 변수를 이용하여 아래와 같은 프로세스 실행 순서 제어를 위한 동기화를 제공한다는 사실이다.

모니터의 프로세스 실행 순서 제어 동기화

  • 특정 프로세스가 아직 실행될 조건이 되지 않으면 wait를 통해 실행을 중단한다.
  • 특정 프로세스 실행 조건이 충족된 경우, signal을 통해 실행을 재개한다.

[문제] 다음 중, 틀린 개념을 고르시오.

  1. 뮤텍스 락은 임계 구역을 잠금으로써 프로세스 간의 상호 배제를 이룬다.
  2. 세마포는 공유 자원이 여러 개 있는 임계 구역 문제도 해결할 수 있는 동기화 도구다.
  3. 모니터는 세마포에 비해 사용자가 사용하기 편리한 동기화 도구로 조건 변수를 사용한다.
  4. 모니터가 조건 변수를 사용함으로 조건변수와 모니터는 동일한 개념이다.

[정답] 4. 모니터가 조건 변수를 사용하지만, 둘은 별개의 개념이다.

profile
꾸준함의 가치를 믿는 개발자

0개의 댓글