본문 바로가기

취업과 기본기 튼튼/빽 투더 기본기

빽 투더 기본기 [OS 2편]. 쓰레드

이 글에서는 Threaad(쓰레드)에 대해 정리해본다.

1. Thread 란

1.1. Process vs Thread

  • Process : 메모리에 올려져있는 실행중인 프로그램.
    • 프로세스간 메모리 영역은 독립적이다. (stack, heap, data, text)
    • 각 프로세스는 별도의 메모리에 할당되며, IPC 통신이 아니면 서로 접근할 수 없다.
  • Thread : 프로세스 내에서 실행되는 흐름의 단위
    • 프로세스 내에 쓰레드 단위로 stack 만 할당받고, heap, data, text 영역은 공유한다.
    • 즉 쓰레드 간에는 데이터 힙 공간을 통해 IPC 를 거치지 않아도 자원 접근, 수정이 가능하다.

쓰레드는 프로세스 내부의 좀 더 경량화된 프로세스이다.

1.2. 왜 쓰는가? (Multi process vs Multi Thread)

멀티 프로세싱의 단점을 보완하고자 멀티 쓰레드가 나왔으므로, 멀티 프로세싱의 단점부터 살펴보자.

  • Multi process
    • 독립적으로 어떤 일을 수행하므로, 문제가 발생해도 다른 프로세스에 영향을 주지 않는다.
    • 하지만, 프로세스 처리는 쓰레드와 비교했을 때 무겁다.
      • Context Switching 에서의 오버헤드
        • CS 가 일어날 때마다 PCB 를 통째로 캐시에 저장, 로드 해야함.
      • IPC 에서의 오버헤드
        • 자원 공유가 번거롭고, 느림.
    • 좀 더 가볍게 여러 테스크를 진행할 수 없을까?
  • Multi Threading
    • 하나의 목적을 가지고 하는 일을 여러 개로 나눠서 병행처리해야할 경우 쓰레드를 쓰자.
    • Multi prcoess 와 비교했을 때, 다음과 같은 장점이 있다.
      • 프로세스보다 메모리 사용가 적다. (Stack 만 할당하므로)
      • 쓰레드간 데이터 통신이 빠르다. (Heap 을 공유, 접근 가능하므로)
      • 수행 속도가 일반적으로 빠르다. (CS 시, Stack 영역만 처리하므로)
    • 다음과 같은 단점이 있다.
      • 쓰레드간 자원 공유에 대한 문제 (동기화, synchronization)
      • 설계와 제어가 까다롭다.

1.3. User-level Thread vs Kernel-level Thread

커널 레벨 쓰레드와 유저 레벨 쓰레드는 생성 주체가 누구냐에 따라 구분된다. (매우 헷갈림 주의)

  • User-level Thread
    • 프로그래머커널에 의존적이지 않게, 라이브러리를 통해 생성하는 쓰레드가 유저 레벨 쓰레드이다.
      • 이렇게 생성된 쓰레드는, 커널에게는 보이지 않는다.
        즉 커널은 프로세스 그 자체만 알지 , 내부의 유저 쓰레드는 모른다.
      • 커널 스케쥴링의 기본 단위가 즉 프로세스 단위다.
    • 커널이 전혀 관여하지 안고, 프로세스에서 관리한다.
      즉, 프로세스가 자체적인 쓰레드 스케줄링을 가진다.
      • 모드 변경이 필요없어 생성과 관리가 빠르다.
      • 즉, 쓰레드간 CS 시, 커널 스케쥴러를 호출하지 않으므로, 오버헤드가 적다.
    • 하지만, 프로세스 내 하나의 쓰레드가 커널에 의해 블록되면 해당 프로세스가 통째로 블록된다.
      • 이를 해결하는 프로그래밍과 결과 예측이 매우 어렵다.
  • Kernel-level Thread
    • 프로그래머 요청에 따라 쓰레드를 생성하고 스케줄링하는 주체가 커널이면 커널 레벨 쓰레드라고 한다.
      • 커널 스케쥴링의 기본 단위가 즉 프로세스 단위가 아닌, 쓰레드 단위다.
      • 하나의 프로세스는 적어도 하나의 커널 쓰레드에게 관리된다.
        • 단일 프로세스 = 1개의 쓰레드
    • 하지만 유저 <-> 커널 모드 전환에서 오버헤드가 크다.
      • 같은 프로세스 내 쓰레드 전환(유저 레벨)의 경우 CS 비용이 적지만,
        다른 프로세스 간의 쓰레드 전환(커널 레벨)의 경우 이 비용이 크기 때문이다.
    • 현대 대부분의 OS 는 이 방식을 채택

다시 한 큐에 정리하면,

- 커널 레벨 쓰레드
장점 : 안전성, 기능의 다양성
단점 : 커널에서 기능을 제공하기 때문에 성능 저하

- 유저레벨 쓰레드

장점 : 전환 필요없기때문에 성능 좋음
단점 : 프로세스 내에 쓰레드가 하나만 블로킹 되어도 나머지 쓰레드가 작동하기 어려움

출처 : https://givemesource.tistory.com/43

2. 다중 쓰레드 모델

보통 운영체제는 유저레벨 쓰레드와 커널레벨 쓰레드 모두 제공한다.
두 쓰레드간의 관계 모델 유형을 살펴보면 다음과 같이 3가지로 분류할 수 있다.

  • 다대일 (N-to-one) 모델
    • 효율적이긴 하지만 한 스레드가 블락당할 경우 전체 프로세스가 봉쇄된다.
    • 진정한 병렬성의 개념이 없다.
  • 일대일 (One-to-one) 모델
    • 다대일 보다 더 많은 병렬성을 제공한다.
    • 많은 쓰레드가 생성됐을 시, CS 비용이 크다.
  • 다대다 (N-to-M) 모델
    • 위 두 모델의 문제점을 어느 정도 해결한 모델