인프런 워밍업 클럽 스터디 3기 - CS <2주 발자국>

프로세스 동기화

프로세스 간 통신(IPC: Inter-Process Communication)

프로세스는 독립적인 실행 단위이기 때문에 기본적으로 타 프로세스의 메모리 영역에 접근할 수 없다. 서로 다른 프로세스들이 데이터를 교환하고 협력할 수 있도록 도와주는 메커니즘이다.

통신의 분류는 크게 3가지로 분류될 수 있다.

  1. 같은 컴퓨터 내 프로세스 간 통신

  2. 같은 프로세스 내 스레드 간 통신

  3. 네트워크를 이용한 원격 프로세스 간 통신

같은 컴퓨터 내 프로세스 간 통신
  1. 파일

    파일은 프로세스 들이 하나의 파일을 이용해 데이터를 쓰고 읽어서 데이터를 전달하는 방식이다.

  2. 파이프

    파이프는 운영체제가 생성한 특별한 메모리 구조로 한 쪽 프로세스는 쓰고 다른 쪽 프로세스는 읽는 단방향 통신이다.

    익명 파이프(anonymous pipe) : 부모-자식 처럼 관련된 프로세스 간 통신

    명명 파이프(named pipe) : 이름이 있는 파일형태로 관련이 없는 프로세스 간 통신

  3. 메시지 큐

    운영체제가 관리하는 큐 형태의 자료구조로 메시지 단위로 데이터를 주고 받는 형식이다. 비동기 통신이 가능하고 메시지 단위여서 데이터 구조화에 용이하다.

  4. 공유 메모리

    여러 프로세스가 동시에 접근 가능한 메모리 영역을 운영체제가 할당하여 공유 메모리 영역을 통해 읽고 쓸 수 있다. 단 동기화 문제로 인해 세마포어, 뮤택스 등의 관리가 필요하다.

  5. 시그널

    특정 이벤트(kill 혹은 ctrl+c)를 발생을 알리는 비동기 통신 메커니즘. 데이터 전달 보다는 프로세스 제어에 사용된다.

스레드 간 통신

스레드는 프로세스 내의 존재하는 실행 단위로 같은 프로세스내의 스레드들은 기본적으로 코드, 데이터, 힙 영역을 공유한다.

이때 전역 변수, 힙 영역을 통해 데이터를 쉽게 주고 받는다.

공유 자원에 대한 동시 접근 시 동기화가 매우 중요하여 동기화 도구들을 활용한다.

  • 뮤텍스(Mutex) : 한 번에 하나의 스레드만 공유 자원 접근할 수 있게 한다.

  • 조건 변수(Condition Variable) : 특정 조건이 충족될 때까지 스레드를 대기 상태로 두었다가 조건이 충족되면 통지하는 방식

  • 세마포어(Semaphore) : 0이상의 정수 값을 가지고 있고 0이되면 다른 스레드의 접근을 막는 방식. 프로세스가 자원을 얻을 때 wait(P 연산)으로 세마 포어 값을 감소시키고 signal(V 연산)으로 자원을 반환할 때 세마포어 값을 증가시킨다.

    wait(S):
      S -= 1
      if (S < 0):
        현재 스레드를 대기 큐에 넣고 대기 상태로 전환
    signal(S):
      S += 1
      if (S <= 0)
        대기 큐에서 한 개의 스레드를 깨워 실행 준비 상태로 전환

네트워크를 통한 원격 프로세스 간 통신
  1. 소켓(Socket)

    네트워크 프로토콜(TCP/IP, UDP)를 활용하여 서로 다른 컴퓨터의 프로세스가 데이터를 주고 받을 수 있도록 하는 추상화된 인터페이스

    네트워크를 통해 통신 가능하며 표준화된 인터페이스라는 장점이 있지만, 데이터의 직렬화/역직렬화의 문제와 네트워크 프로그래밍의 복잡성이 존재한다.

  2. RPC(Remote Process Call)

    다른 컴퓨터에 있는 프로세스 함수를 로컬 함수 처럼 호출할 수 있도록 해주는 기술.

    내부적으로 소켓 통신 등을 사용하고 호출 과정, 파라미터 전달, 결과 반환을 추상화하여 원격 함수 호출을 구현할 수 있다.

    분산 시스템 개발에 용이하지만 성능 오버헤드 문제와 호출 실패 시 처리가 복잡하다.

공유자원과 임계구역

공유자원(Shared Resource)

여러 프로세스(또는 스레드)들이 함께 사용하는 자원(메모리, 파일, 변수)를 의미한다.

동시에 여러 프로세스가 공유하기 때문에 접근 순서에 따라 결과가 달라질 수 있다.

컨텍스트 스위칭등으로 인해 결과를 예측하기 어려운 상황이 발생하며 이를 동기화 문제 (Synchronization Problem)이라고 한다.

임계구역(Critical Section)

공유 자원에 접근할 때 반드시 보호해야 하는 코드 영역

여러 프로세스가 동시에 임계구역에 접근하면 의도치 않은 결과가 발생하게 된다.

접근 순서와 타이밍 문제로 발생하는 경쟁적 상태를 경쟁 조건(Race Condition)이라고 한다.

임계 구역 문제 해결을 위한 조건

  1. 상호 배제(Mutual Exclusion)

    한 번에 단 하나의 프로세스만 임계구역에 접근 가능

  2. 진행(Progress)

    임계구역을 사용하지 않는 프로세스가 다른 프로세스의 접근을 방해하지 않아야 한다.

  3. 유한 대기(Bounded Waiting)

    어떤 프로세스든 일정한 시간 내에 반드시 임계 구역에 진입할 수 있어야 한다.

    프로세스의 기아 상태(Starvation)를 피하고 프로세스의 공평한 자원 할당이 필요하다.

임계구역 문제 해결 방법

세마포어

운영체제 차원에서 제공하는 동기화 도구로 공유자원의 접근 권한을 관리하는 정수형 변수이다.

세마포어의 값은 일반적으로 자원의 개수를 의미하며 보통 이진(0,1) 세마포어를 사용하여 임계 구역을 보호한다.

공유 자원에 접근하려는 프로세스를 대기 큐에 넣고 운영체제가 대기 큐에 있는 프로세스에게 세마포어를 통해 접근 권한을 제어한다.

두 가지 기본 연산을 통해 관리한다.

  • wait() : 자원이 없으면 프로세스는 자원이 확보될 때까지 대기 상태로 들어간다.

  • signal( ) : 자원을 사용한 후 다시 자원을 반납하여 대기중인 프로세스에게 공유자원을 사용하게 한다.

int s = 1;
wait(s)
// 임계 구역 사용
signal(s) 

단 signal()과 wait()의 호출 순서가 잘못되면 세마포어 값이 혼동되어 데이터 손상이나 교착상태(deadlock)를 유발할 수 있다.

뮤텍스(Mutex)

세마포어의 특수한 형태로 오직 한 프로세스만 임계구역 접근을 허용하는 이진 세마포어(binary semaphore)이다.

C언어에서 POSIX 스레드 API를 사용하면 pthread_mutex_lock()pthread_mutex_unlock()으로 표현된다.

모니터

운영체제가 아니라 프로그래밍 언어 수준에서 제공하는 동기화 메커니즘이다.

모니터는 공유 데이터와 이를 조작하는 프로시저(메서드)를 하나의 객체로 묶은 형태로 제공한다.

프로그래머는 직접 wait(), signal()을 호출할 필요 없이 언어에서 자동으로 동기화 관리를 한다.

public class SharedCounter {
    private int count = 0;
​
    public synchronized void increment() {
        count++;
    }
​
    public synchronized int getCount() {
        return count;
    }
}

자바에서는 synchronized 키워드를 통해 동기화 코드를 작성하게 된다.

synchronized 메서드를 호출하는 동안에는 다른 synchronized 메서드가 접근 불가능 핟록 배타적 접근이 보장된다.

댓글을 작성해보세요.

채널톡 아이콘