lhywk 님의 블로그

[운영체제 OS] Thread 본문

Operating System

[운영체제 OS] Thread

lhywk 2026. 2. 1. 15:17

1. 프로세스와 쓰레드

과거의 프로세스는 자원 관리와 실행을 동시에 담당하는 무거운 프로세스(Heavyweight Process)였다. 현대 운영체제는 이를 효율적으로 관리하기 위해 두 역할을 분리했다.

  • 프로세스: 자원 소유의 단위. 메모리(코드, 데이터), 파일, 시스템 자원을 담는 컨테이너 역할.
  • 쓰레드: 실행의 단위. 프로세스 내에서 실제 CPU를 할당받아 코드를 수행하는 제어 흐름. 경량 프로세스(Lightweight Process)라고도 불린다.

2. 프로세스와 쓰레드의 4가지 모델

운영체제는 프로세스와 쓰레드의 개수에 따라 네 가지 방식으로 나뉜다.

  • 단일 프로세스, 단일 쓰레드: 가장 전통적인 방식 (예: MS-DOS).
  • 단일 프로세스, 다수 쓰레드: 우리가 흔히 말하는 멀티쓰레딩(예: 웹 브라우저, 워드).
  • 다수 프로세스, 단일 쓰레드: 여러 프로그램을 동시에 띄우는 고전적 멀티태스킹.
  • 다수 프로세스, 다수 쓰레드: 현대 운영체제의 표준 (예: Windows, Linux).

3. 멀티쓰레딩의 내부 구조와 장점

3.1 내부 구조의 차이

  • 공유 요소: 프로세스 내의 모든 쓰레드는 사용자 주소 공간(코드, 데이터)열린 파일 등을 공유한다.
  • 독립 요소: 각 쓰레드는 자신만의 TCB(Thread Control Block),레지스터 문맥, 그리고 독립적인 스택(Stack)을 가진다.

3.2 쓰레드의 주요 장점

  • 경제성: 생성 및 종료가 빠르고, 문맥 교환(Context Switching) 오버헤드가 적다.
  • 응답성: 긴 작업이 실행되는 동안에도 다른 쓰레드가 사용자 입력에 즉각 반응할 수 있다 (전면/후면 작업 분리).
  • 자원 공유: 별도의 복잡한 통신(IPC) 기법 없이 메모리를 공유하여 데이터를 주고받는다.
  • 멀티코어 활용: 여러 쓰레드를 각각 다른 CPU 코어에서 병렬로 실행할 수 있다.

4. 사용자 수준 쓰레드와 커널 수준 쓰레드

구분 사용자 수준 쓰레드 (ULT) 커널 수준 쓰레드 (KLT)
관리 주체 사용자 라이브러리 (pthread 등) 운영체제(커널)
속도 매우 빠름 (모드 전환 없음) 상대적으로 느림 (시스템 콜 필요)
블로킹 하나가 막히면 전체가 멈춤 한 쓰레드가 막혀도 다른 쓰레드 실행 가능
병렬성 멀티코어 활용 불가 멀티코어 활용 가능

ULT > KLT > 프로세스 순서로 빠르다. (ULT는 KLT보다 약 28배, 프로세스보다 수백 배 빠를 수 있음)

5. 쓰레드 상태와 동기화

5.1 쓰레드 상태 변화

  • 수행 (Running): 현재 CPU를 할당받아 명령을 실행하고 있는 상태.
  • 준비 (Ready): 실행할 준비가 되었지만, 아직 자신의 차례가 아니어서 CPU를 기다리는 상태 (준비 큐에서 대기).
  • 블록 (Blocked / Wait): 입출력(I/O) 작업과 같은 특정 이벤트가 완료되기를 기다리며 실행을 멈춘 상태. CPU가 비어있어도 실행될 수 없다.
  1. 쓰레드 A (수행): 처음엔 CPU를 점유하고 실행.
  2. A → 블록: 실행 도중 '입출력 요청'이 발생하자, 스스로 블록 상태가 됨 (CPU 반납).
  3. 쓰레드 B (수행): A가 블록 되자, 준비 상태에 있던 B가 CPU를 할당받아 수행 상태가 됨.
  4. B → 준비: B에게 할당된 시간(Time Slice)이 만료되자('시간 할당량 완료'), 다시 준비 상태로 돌아감.
  5. 쓰레드 C (수행): 이제 C가 CPU를 할당받아 수행됨.
  6. A → 준비: 그사이 A가 요청했던 '입출력'이 완료되자, A는 다시 CPU를 받을 수 있는 준비 상태로 돌아옴.

5.2 쓰레드 동기화 필요

여러 쓰레드가 공유 자원에 동시에 접근하여 값을 수정할 때 경쟁 상태(Race Condition)가 발생할 수 있다. 이를 방지하기 위해 임계 구역(Critical Section)을 설정하고, 한 번에 하나만 접근하게 하는 상호 배제(Mutual Exclusion)가 필요하다.

 

6. Linux/Android 프로세스와 쓰레드 관리

6.1 Linux 프로세스와 쓰레드 관리

  • 준비 (Ready / Runnable)
    • CPU를 할당받으면 즉시 실행될 수 있지만, 현재 스케줄러의 선택을 기다리는 상태.
  • 수행 중 (Executing / Running)
    • 스케줄러에 의해 선택되어 현재 CPU에서 명령을 실행하고 있는 상태.
  • 잠듦 상태 (Sleeping / Blocked)
    • 특정 사건(Event)을 기다리며 실행이 중단된 상태. Linux에서는 두 종류로 나뉨.
    • 인터럽트 가능 잠듦 (Interruptible Sleep): 기다리는 사건이 발생하거나, 시그널(Signal)을 받으면 깨어나서 '준비' 상태로 돌아감.
    • 인터럽트 불가 잠듦 (Uninterruptible Sleep): 오직 기다리는 사건이 발생해야만 깨어남. 시그널을 받아도 무시.
  • 정지 (Stopped)
    • 실행이 일시적으로 멈춘 상태.
  • 좀비 (Zombie)
    • 프로세스가 실행을 마치고 종료(exit())했지만, 부모 프로세스가 아직 자식의 종료 상태를 확인(수거) 하지 않은 상태.

상태 변화의 주요 원인

  • 스케줄링 (Scheduling): 준비 상태의 프로세스를 수행 중 상태로 전환.
  • 사건 (Event): 주로 입출력(I/O) 작업의 시작과 완료를 의미.
  • 시그널 (Signal): 프로세스에 특정 이벤트를 알리는 소프트웨어 인터럽트.

6.2 Android 프로세스와 쓰레드 관리

  • onCreate(): (생성)
    • 액티비티가 처음 생성될 때 단 한 번 호출.
  • onStart(): (시작)
    • 액티비티가 사용자에게 보이기 직전에 호출.
  • onResume(): (재개/실행)
    • 액티비티가 화면 맨 앞에 나타나 사용자와 상호작용이 가능할 때 호출.
  • onPause(): (일시정지)
    • 다른 액티비티가 위에 나타나는 등 포커스를 잃기 시작할 때 호출.
  • onStop(): (멈춤)
    • 액티비티가 사용자 눈에 더 이상 보이지 않게 될 때 호출.
  • onRestart(): (재시작)
    • onStop() 상태에 있던 액티비티가 다시 화면에 표시되기 직전에 호출. 호출된 후에는 onStart()가 이어짐.
  • onDestroy(): (소멸)
    • 액티비티가 메모리에서 완전히 사라지기 직전에 호출.

액티비티의 수명

  • 전체 수명 (Entire Lifetime): onCreate() ~ onDestroy()
    • 액티비티가 메모리에 생성되어 소멸되기까지의 전체 기간.
  • 가시적 수명 (Visible Lifetime): onStart() ~ onStop()
    • 액티비티가 사용자에게 보이는 기간. onPause() 상태에서는 포커스는 없지만 화면에는 보이므로 가시적 수명에 포함.
  • 전면 수명 (Foreground Lifetime): onResume() ~ onPause()
    • 액티비티가 화면 맨 앞에서 사용자와 상호작용하는 기간.

출처

  • William Stallings, 운영체제 내부구조 및 설계원리

'Operating System' 카테고리의 다른 글

[운영체제 OS] Memory Management  (1) 2026.02.01
[운영체제 OS] Deadlock  (1) 2026.02.01
[운영체제 OS] Concurrency  (0) 2026.02.01
[운영체제 OS] Process  (0) 2026.02.01
[운영체제 OS] Operating System Overview  (0) 2026.02.01