[CS] 프로세스(스레드) 동기화

sarang_daddy·2023년 2월 12일
0

비동기 학습 때 자원의 일관성을 위해 필요하다고 한 "동기화"에 대해 알아보자.

컴퓨터 공학 기초 강의 - 한빛미디어 내용을 학습용으로 정리한 내용입니다 직접 강의를 보심을 추천 드려요.

🔎 프로세스(스레드) 동기화란?

: 자원의 일관성을 보장하기 위해 프로세스들의 수행 시기를 맞추는 것.
: 실행의 문맥을 갖는 모든 대상은 동기화 대상이기에 스레드도 동기화 대상이다.

동시다발적으로 실행되는 프로세스들은 서로 협력하며 영향을 주고 받는다.
이 과정에서 자원의 일관성을 보장해야 한다.

이를 위해 동기화는 아래와 같이 2가지가 이루어진다.

  1. 실행 순서 제어 : 프로세스를 올바른 순서대로 실행하기
  2. 상호 배제 : 동시에 접근해서는 안 되는 자원에 하나의 프로세스만 접근하게 하기

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

Writer라는 값을 저장하는 프로세스와 Reader라는 저장된 값을 읽는 프로세스가 있다고 했을 때,
두 프로세스는 무작정 실행되서는 안된다.
실행의 순서가 있기 때문이다. Reader는 저장된 값이 존재한다는 조건이 만족 되어야만 한다.

상호 배제를 위한 동기화

공유가 불가능한 자원의 동시 사용을 피하기 위한 동기화이며
한 번에 하나의 프로세스만 접근해야 하는 자원에 동시 접근을 막기 위함을 의미한다.
ex) 프린터 : 한 번에 하나씩만 작업이 가능하다.
ex) Bank account problem : 계좌의 접근이 동시적으로 일어나면 잔액이 중첩되서 예상 못한 결과가 나올 수 있다.


⛔️ 임계구역 - 동시에 접근하면 안되는 자원

공동으로 이용하는 변수, 파일, 장치 등의 자원을 공유 자원이라 하고,
공유 자원에 접근하는 코드 중 동시에 실행하면 문제가 발생하는 코드 영역을 임계 구역이라 한다.

  • 공유 자원 : 여러 프로세스 혹은 스레드가 공유하는 자원
    ex) 전역 변수, 파일, 입출력장치, 보조기억장지 등

  • 임계 구역 : 동시에 실행하면 문제가 발생하는 자원에 접근하는 코드 영역
    ex) 총합 변수, 잔액 변수

임계 구역에 진입하고자 하면 진입한 프로세스 이외에는 대기해야 한다.
임계 구역에 동시에 접근하면 자원의 일관성이 깨질 수 있다.
이를 레이스 컨디션(race condition)이라 한다.

운영체제가 임계구역 문제를 해결하는 세가지 원칙

  1. 상호배제(mutual exclusion)
    : 한 프로세스가 임계 구역에 진입했다면 다른 프로세스는 들어올 수 없다.
  2. 진행(progress)
    : 임계 구역에 어떤 프로세스도 진입하지 않았다면 진입하고자 하는 프로세스는 들어갈 수 있다.
  3. 유한 대기(bounded waiting)
    : 한 프로세스가 임계 구역에 진입하고 싶다면 언젠가는 임계 구역에 들어올 수 있어야 한다.
    (임계 구역에 들어오기 위해 무한정 대기해서는 안된다.)

✅ 동기화 기법

뮤덱스 락(자물쇠)

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

let lock = boolean;

acquire() {
    while (lock === true) {     // 임계구역이 잠겨있다면
        ~                       // 임계구역이 잠겨있는지 반복적으로 확인 (busy waiting)
    }
    lock = true;                // 임계구역이 잠겨 있지 않다면 임계구역 잠금
}

release() {
    lock = false;               // 임계구역 작업이 끝났으니 잠금 해제
}
  • acquire 함수

    • 프로세스가 임계 구역에 진입하기 전에 호출
    • 임계 구역이 잠겨 있다면 열릴 때까지 임계 구역을 반복적으로 확인
    • 임계 구역이 열려 있다면 임계 구역을 잠그고 들어가기
  • release 함수

    • 임계 구역에서의 작업이 끝나고 호출
    • 현재 잠긴 임계 구역을 열기

단점 : (계속 체크하면서 무한히 기다리는) Busy Waiting 이 적용된다. CPU 낭비


세마포(신호기)

: 일반화된 방식의 동기화 도구
: 공유 자원이 여러 개 있는 경우`에도 적용 가능한 동기화 기법
: 임계 구역 앞에서 멈춤 신호를 받으면 대기, 가도 좋다는 신호를 받으면 임계 구역 진입.

var S = // 임계 구역에 진입할 수 있는 프로세스의 개수(사용 가능한 공유 자원의 수)의 전역 변수S

wait() // 입계 구역 진입 가능 여부 "OK" or "NOPE" 를 알려주는 wait 함수
// 입계 구역
signal() // 입계 구역 진입을 기다리던 프로세스에게 "OK" 신호를 주는 signal 함수
// ex)
wait() {
  while (S <= 0) // 임계 구역에 진입할 수 있는 프로세스 개수가 0 이하라면
    ; 			 // 사용할 수 있는 자원이 있는지 무한반복 (Busy Waiting)
  S--;			 // 임계 구역에 진입할 수 있는 프로세스가 1개 이상면 S 감소하고 진입
}

signal() {
  S++			 // 임계 구역에서의 작업을 마치고 S 증가 (내가 빠져나감)
}

Busy Waiting

: 뮤덱스 락처럼 Busy Waiting이 적용된다.

  • 세마포 기법에서는 대기 상태와 준비 상태를 활용해서 Busy Waiting을 해결 할 수 있다.
    - 사용할 수 있는 자원이 없을 경우 대기 상태 로 만든다. (해당 프로세스 PCB를 대기 큐에 삽입)
    - 사용할 수 있는 자원이 생겼을 경우 대기 큐의 프로세스를 준비 상태 로 만든다.
    (해당 프로세스의 PCB를 대기 큐에서 꺼내 준비 큐에 삽입.)

세마포를 활용한 싱행 순서 동기화

: 세마포는 상보 배제 동기화 + 실행 순서 동기화가 가능하다.

  • 세마포의 변수 S를 0으로 두고,
  • 먼저 실행할 프로세스 뒤에 signal 함수,
  • 다음에 실행할 프로세스 앞에 wait 함수를 붙인다.
P1
// 임계 구역
signal()

P2
Wait()
// 임계 구역

// P1이 먼저 실행되면 바로 들어간다.
// P2가 먼저 실행되면 Wait(대기)로 들어가서 P1이 먼저 들어간다.

단점 : 세마포는 임계구역 앞위로 wait(), signal()을 매번 호출해야해서 불편한다.
(프로젝트가 커질수록 누락, 순서의 뒤바낌 등 문제발생 가능성이이 커진다)


모니터

: 개발자가 사용하기 편리한 도구
: 상호 배제와 실행 순서 동기화 모두를 제공하는 동기화 기법

  • 상호 배제
    - 인터페이스를 위한 큐
    - 공규 자원에 접근하고자 하는 프로세스를 (인터페이스를 위한) 큐에 삽입
    - 큐에 삽입된 순서대로 공유 자원 이용

  • 실행 순서 제어
    - 조건 변수(프로세스나 스레드의 실행 순서를 제어하기 위해 사용하는 변수) 이용한다.
    - 특정 프로세스가 아직 실행될 조건이 되지 않았을 때는 wait를 통해 실행을 중단.
    - 특정 프로세스가 실행될 조건이 충족되었을 때에는 signal로 재개.


🔒 교착상태(Dead lock)

일어나지 않을 일을 계속 기다리면서 동작이 멈추는 상태

교착상태 파악하기

자원 할당 그래프로 상황 파악하기

  • 어떤 프로세스가 어떤 자원을 할당 받아 사용 중인지 확인 가능하다.
  • 어떤 프로세스가 어떤 자원을 기다리고 있는지 확인 가능하다.


일반적인 자원할당 그래프


교착상태가 발생된 자원할당 그래프는 원의 형태를 가진다.

교착 상태가 발생한 근본적인 이유 파악하기

  • 교착 상태가 발생한 조건
  1. 상호 배제 : 한 프로세스가 사용하는 자원을 다른 프로레스가 사용할 수 없는 상태
  2. 점유와 대기 : 자원을 할당 받은 상태에서 다른 자원을 기다리는 상태
  3. 비선점 : 어떤 프로세스도 다른 프로세스의 자원을 강제로 빼앗지 못하는 상태
  4. 원형 대기 : 프로세스들이 원의 형태로 자원을 대기하는 상태

위 네 가지 조건 중 하나라도 만족하지 않으면 교착 상태가 발생하지 않는다.
위 네 가지 조건을 모두 만족하면 교착상태가 발생할 수 있다.


🔓 교착상태(Dead lock) 해결방법

교착 상태 예방

: 교착 상태 발생 4가지 조건 중 하나를 없애는 방법

  1. 상호 배제 : 없애기 현실적으로 불가능
  2. 점유와 대기 : 특정 프로세스에게 자원 모두 할당 or 아에 할당 주지 않는다. -> 자원의 활용률 저하 발생
  3. 비선점 : 특정 프로세스에게만 선점이 가능하도록 한다. -> 모든 자원 선점권을 줄 수는 없다.
  4. 원형 대기 : 자원에 번호를 붙이고 오름차순으로 할당하면 원형 대기는 발생하지 않는다. (원형 -> 일렬)
    • 자원에 번호를 주는 것은 어려운 작업
    • 번호를 준다(조건이 추가) 자원의 활용률 저하 발생

교착 상태 예방 방법은 교착 상태 방지가 가능하나 부작용이 따른다.

교착 상태 회피

: 교착 상태를 무분별한 자원 할당으로 인해 발생 했다고 간주
: 교착 상태가 발생하지 않을 만큼 조심히 할당하는 방법
: 배분할 수 있는 자원의 양을 교착 상태가 발생되지 않도록 조절

  • 안전 상태만을 유지하도록 자원을 할당하는 방식
  • 안전 상태란? 교착 상태 없이 모든 프로세스가 자원을 할당 받고 종료될 수 있는 상태
  • 은행원 알고리즘 공부해보기

교착 상태 검출 후 회복

: 교착 상태 발생 후 조치
: 프로세스가 자원을 요구하면 일단 항당하고 교착 상태가 발생하면 회복 시킨다.

  • 선점을 통한 회복
    - 교착 상태가 해결될 때까지 한 프로세스씩 자원을 몰아준다.

  • 프로세스 강제 종료를 통한 회복
    - 교착 상태 프로세스 모두 강제 종료(내역 상실)
    - 교착 상태 해결될 때까지 한 프로세스씩 강제 종료

profile
한 발자국, 한 걸음 느리더라도 하루하루 발전하는 삶을 살자.

0개의 댓글