Machineboy空

동기화 기법: 뮤텍스 락, 세마포, 모니터 본문

Computer/CS

동기화 기법: 뮤텍스 락, 세마포, 모니터

안녕도라 2024. 1. 16. 12:20

프로세스 동기화 기법은 여러가지가 있지만 그중 대중적으로 알려진 뮤텍스 락, 세마포, 모니터

프로그램 언어, 코드 짜진 것 보고 이해해보는 것도 좋은 방법

 

  • 실행 순서를 위한 동기화
  • 상호 배제를 위한 동기화

뮤텍스 락 (Mutex Lock)

상호 배제를 위한 동기화 도구(자물쇠 역할)

  • 탈의실  = 1번에 1명만 이용할 수 있는 공유 자원, 임계 구역
  • 손님 = 프로세스
  • 탈의실이 이용중이라는 표시 = 자물쇠 (뮤텍스 락)


  • 뮤텍스 락의 단순한 형태: 전역 변수 하나, 함수 두 개
    • 자물쇠 역할: 프로세스들이 공유하는 전역 변수 lock
    • 임계 구역을 잠그는 역할: acquire함수
    • 임계 구역의 잠금을 해제하는 역할: release 함수

c 언어에서 ;를 찍어두면 무한 반복 즉, 계속 잠겨있는지 확인하라는 뜻

acquire 함수 프로세스가 임계 구역에 진입하기 전에 호출

임계 구역이 잠겨있다면?
임계 구역이 열릴 때까지 (lock이 false가 될 때까지) 임계 구역을 반복적으로 확인

임계 구역이 열려있다면?
임계 구역을 잠그기(lock을 true로 바꾸기)
release 함수 임계 구역에서의 작업이 끝나고 호출

현재 잠긴 임계 구역을 열기(lock을 false로 바꾸기)

 

bank account 예제


 

바쁜 대기(busy waiting) : 무한히 대기하며 반복적으로 확인하는 것

while문으로 계속해서 쉼없이 살펴보는 것이 그리 좋은 방법은 아니다.

프로그래밍 언어(C++, python 등)에서도 제공하긴 하는데 이렇게 간단하게 이루어지진 않음.


세마포(Semaphore)

철도 신호기에서 유래된 말

올라가 있으면 지나가기, 내려가 있으면 멈추기


좀 더 일반화된 방식의 동기화 도구

공유 자원이 여러 개 있는 경우에도 적용 가능

뮤텍스 락은 공유 자원이 하나인 경우를 상정한 것이었음

이진 세마포는 뮤텍스 락과 거의 유사, 여기에서는 카운팅 세마포를 이야기

  • 임계 구역 앞에서 멈춤 신호를 받으면 잠시 기다리기
  • 임계 구역 앞에서 가도 좋다는 신호를 받으면 임계 구역 진입

 


  • 세마포의 단순한 형태: 전역 변수 하나, 함수 두 개
    • 임계 구역에 진입할 수 있는 프로세스의 개수(사용 가능한 공유 자원의 개수)를 나타내는 전역 변수 S
    • 임계 구역에 들어가도 좋은지, 기다려야 할지를 알려주는 wait함수
    • 임계구역 앞에서 기다리는 프로세스에 '이제 가도 좋다'고 신호를 주는 signal 함수

 

*Busy Waiting이 또 실행되고 있음 >> CPU사이클 낭비!

예제


busy waiting보다 더 영리한 방법

CPU사이클 낭비를 줄이는 법

  • 사용할 수 있는 자원이 없을 경우 대기 상태로 만듦
    • 해당 프로세스의 PCB를 대기 큐에 삽입
  • 사용할 수 잇는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태로 만듦
    • 해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입
     

busy waiting을 하지 않을 때


세마포(semaphore)는 상호배제를 위한 동기화를 위한 방법이기도 하지만

실행순서 동기화에 쓰이기도 한다.

P1이 먼저 실행되든 P2가 먼저 실행되든 P1-P2 실행순서가 된다


모니터(Monitor)

세마포는 강력한 동기화 도구긴 하지만

매번 임계구역 앞뒤로 wait(),signal()을 호출해야 할까?

그러다 실수라도 한다면?

이런 문제들은 디버깅도 힘들다

 

그래서 등장한 모니터

사용자(개발자)가 다루기에 편한 동기화 도구

 

ex.모니터를 사용하는 언어로 대표적인 JAVA

 

상호배제를 위한 동기화,실행순서를 위한 동기화 모두 지원

 

  • 상호 배제를 위한 동기화
    • 모니터는 공유자원과 공유자원에 접근하기 위한 통로를 묶어서 관리한다.
    • 공유자원에 접근하고자 하는 프로세스와 스레드는 특정 통로,인터페이스를 통해서만 접근하도록 만든다.
    • 인터페이스를 위한 큐 (대기열)
    • 공유자원에 접근하고자 하는 프로세스를 (인터페이스를 위한) 큐에 삽입
    • 큐에 삽입된 순서대로(한 번에 하나의 프로세스만) 공유 자원 이용
     

 

 

  • 실행 순서 제어를 위한 동기화
    • 조건 변수(condition variable) 이용
      • 프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 특별한 변수
      • wait와 signal 함수를 호출할 수 있는 변수
        • 조건변수.wait(): 대기 상태로 변경, 조건 변수에 대한 큐에 삽입
        • 조건변수.signal(): wait으로 대기 상태로 접어든 조건변수를 실행 상태로 변경
    • 조건 변수마다 큐가 만들어져 있다 (조건 변수에 대한 큐)
      • 상호 배제를 위한 큐와 다르다!
    • 방법
      1. 특정 프로세스가 아직 실행될 조건이 되지 않았을 때에는 wait를 통해 실행을 중단한다.
      2. 특정 프로세스가 실행될 조건이 충족되었을 때에는 signal을 통해 실행을 재개한다.

 

  • 모니터 안에는 하나의 프로세스만이 있을 수 있다
    • 엄밀히 말하면 2가지 방식
      • wait()를 호출했던 프로세스는 signal()을 호출한 프로세스가 모니터를 떠난 뒤에 수행을 재개
      • signal()을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal()을 호출한 프로세스의 수행을 재개