프로세스 동기화 (2)

.·2023년 12월 1일

프로세스 동기화 기법

  1. Mutax lock
  2. Semaphore
  3. Monitor

1. Mutax Lock

상호 배제를 위한 동기화 도구(자물쇠 역할), mutax lock
실행 순서 동기화 X, 상호 배제 동기화 O


임계 구역(Critical Section)을 가진 스레드들의 실행시간이 서로 겹치지 않고 각각 단독으로 실행되게 하는 기술

mutax lock 의 단순한 형태
전역 변수 하나, 함수 두 개

  • 자물쇠 역할 : 프로세스들이 공유하는 전역 변수 lock
  • 임계 구역을 잠그는 역할 : acquire 함수
  • 임계 구역의 잠금을 해제하는 역할 : release 함수

(용어 1. 임계 구역(Critical Section))

acquire 함수

  • 프로세스가 임계 구역에 진입하기 전에 호출
  • 임계 구역이 잠겨 있다면
    : 임계 구역이 열릴 때까지 (Lock 이 false가 될 때 까지) 임계 구역을 반복적으로 확인
  • 임계 구역이 열려 있다면
    : 임계 구역을 잠그기 (Lock 을 true로 바꾸기)

release 함수

  • 임계 구역에서의 작업이 끝나고 호출
  • 현재 잠긴 임계 구역을 열기 (lock을 false로 바꾸기)


busy waiting

기다리는 프로세스(쓰레드포함) 공유 자원을 사용할수 있는지 없는지 계속해서 무한 루프를 돌면서 조건문을 체크하는 방식이 busy waiting 이다

이 바쁜대기라고 불리는 busy waiting은 cpu의 자원을 쓸데없이 낭비하기 때문에 좋지 않은 동기화 방식이다.

추후에 해결 ~~


2. Semaphore

세마포어 : 멀티프로그래밍 환경에서 공유 자원에 대한 접근을 제한하는 방법

세마포어는 리소스의 상태를 나타내는 간단한 카운터로 생각할 수 있습니다. 일반적으로 비교적 긴 시간을 확보하는 리소스에 대해 이용하게 되며, 유닉스 시스템의 프로그래밍에서 세마포어는 운영체제의 리소스를 경쟁적으로 사용하는 다중 프로세스에서 행동을 조정하거나 또는 동기화 시키는 기술입니다. 

세마포어(semaphore)는 에츠허르 다익스트라(Edsger Wybe Dijkstra)가 제안한 교착 상태(DeadLock)에 대한 해법으로 두개의 원자적(Atomic) 함수로 제어되는 정수 변수로 멀티프로그래밍 환경에서 공유자원에 대한 접근 제어를 하는 방법으로 사용되며, 1개의 공유되는 자원에 제한된 개수의 프로세스(Process), 또는 스레드(Thread)만 접근할 수 있도록 한다.


원자성(Atomicity)
여러 개의 쓰레드(Thread)가 존재할 때, 특정 시점에서 어떤 메소드(Method)를 2개 이상의 쓰레드가 동시에 호출하지 못하는 것을 말한다.
이러한 원자성을 보장한 함수를 원자적 함수(Atomic Function)이라고 한다.

Semaphore 의 형태

전역 변수 하나, 함수 두 개

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

wait 함수

signal 함수

예제

다시 돌아와서 아까 Mutax 에서 문제가 되었던 busy wait 가 Semaphore 에서도 발생한다.
마치 탈의실 문이 열렸는지/닫혔는지를 0.1 초에 한번씩 확인하는 것과 같다 -> CPU 사이클 낭비

Busy waiting 해결

  • 사용할 수 없는 자원이 없을 경우 Blocked state (대기 상태)로 만듬
    : (해당 프로세스의 PCB를 대기큐(Blocked queue)에 삽입)
  • 사용할 수 있는 자원이 생겼을 경우 대기큐의 프로세스를 Ready state(준비 상태)로 만듬
    : (해당 프로세스의 PCB를 대기 큐에서 꺼내 준비큐(Ready queue)에 삽입)

Busy waiting 을 해결한 Semaphore 예제

Semaphore 를 활용한 실행 순서 동기화

아래의 그림처럼 singal 을 먼저 실행할 함수 뒤에 두고, 다음에 실행할 프로세스 앞에 wait 함수를 붙이면 반드시 P1 이 먼저 실행되고 그다음에 P2 가 실행 된다


Monitor

매번 임계구역(Critical Section) 앞뒤로 wait(), signal() 을 호출해야 하나 ?
그러다 실수라도 하면 ?

이를위해 탄생한 동기화 방법이 Monitor 이다.
Monitor 동기화 방법은 상화 배제 동기화, 실행 순서 제어 동기화 둘 다 가능하다

상호 배제를 위한 동기화

  • 인터페이스를 위한 큐
  • 공유자원에 접근하고자 하는 프로세스를 (인터페이스를 위한) 큐에 삽입
  • 큐에 삽입된 순서대로 (한 번에 하나의 프로세스만) 공유 자원 이용

실행 순서 제어를 위한 동기화

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



모니터 안에는 하나의 프로세스만이 있을 수 있다
모니터 안에 하나의 프로세스만 있을 수 있도록 하는 두가지 방법이 있는데
1. wait() 를 호출했던 프로세스는 signal()을 호출한 프로세스가 모니터를 떠난 뒤에 수행을 재개
2. signal()을 호출한 프로세스의 실행을 일시 중단하고 자신이 실행된 뒤 다시 signal() 을 호출한 프로세스의 수행을 재개


Mutax Semaphore 비교

  • 뮤텍스: 한 쓰레드, 프로세스에 의해 소유될 수 있는 Key🔑를 기반으로 한 상호배제기법
    (상호배제 동기화 O, 실행 순서 동기화 X)
  • 세마포어: Signaling mechanism. 현재 공유자원에 접근할 수 있는 쓰레드, 프로세스의 수를 나타내는 값을 두어 상호배제를 달성하는 기법
    (상호배제 동기화 O, 실행 순서 동기화 O)

Reference

profile
.

0개의 댓글