백엔드 면접 용어 사전
운영체제thread

스레드

프로세스 안의 실행 흐름 단위. 코드·데이터·힙을 공유하고 스택과 레지스터만 따로 갖는다.

프로세스 안에서 실제로 CPU에 올라가 실행되는 단위. 프로세스가 "집"이라면 스레드는 그 안에 사는 "사람"이다.

무엇을 공유하고 무엇을 따로 갖나 — 이 표가 전부다

프로세스 (하나의 주소 공간)
┌──────────────────────────────────────────┐
│  코드 · 데이터 · 힙 · 열린 파일          │  ← 공유
│                                          │
│  ┌────────┐  ┌────────┐  ┌────────┐   │
│  │스레드 1 │  │스레드 2 │  │스레드 3 │   │
│  │ 스택    │  │ 스택    │  │ 스택    │   │  ← 각자
│  │ 레지스터│  │ 레지스터│  │ 레지스터│   │
│  │ PC      │  │ PC      │  │ PC      │   │
│  └────────┘  └────────┘  └────────┘   │
└──────────────────────────────────────────┘
각자 갖는 것
스택함수 호출 흐름이 스레드마다 다르다
레지스터·PC지금 어느 명령을 실행 중인지가 다르다
스레드 로컬 저장소스레드별 데이터를 두기 위해

힙과 전역 변수는 공유한다. 이것이 스레드의 장점이자 모든 문제의 근원이다.

왜 힙 공유가 문제인가

class Counter {
    int count = 0;                    // 힙에 있음 → 모든 스레드가 본다
    void increment() { count++; }     // 이 한 줄이 사실 3단계
}

count++는 기계 수준에서

  • ① 메모리에서 count 읽기 (레지스터로)
  • ② 레지스터 값 +1
  • ③ 레지스터 값을 메모리에 쓰기

①과 ③ 사이에 다른 스레드가 끼어들면 증가가 하나 사라진다. 1000번씩 두 스레드가 돌려도 결과가 2000이 아니다. 이것이 경쟁 조건이다.

반면 지역 변수는 스택에 있어 안전하다 — 스레드마다 스택이 따로이기 때문이다. "지역 변수만 쓰는 메서드는 스레드 안전하다"는 말의 근거가 이것이다.

프로세스 대신 스레드를 쓰는 이유

프로세스스레드
생성 비용큼(주소 공간 복사)작음
컨텍스트 스위칭비쌈(TLB·캐시 무효화)상대적으로 쌈
통신IPC 필요(파이프·소켓)메모리 공유로 즉시
안정성하나가 죽어도 격리하나가 죽으면 프로세스 전체 위험

같은 프로세스 안의 스레드끼리 전환하면 주소 공간이 그대로라 페이지 테이블을 안 바꿔도 되고 TLB도 유지된다. 이것이 "가볍다"의 실체다.

자바에서 — 가상 스레드

전통적으로 자바 스레드는 OS 스레드와 1:1이라 하나당 약 1MB 스택을 잡는다. 수만 개를 만들 수 없다.

자바 21의 가상 스레드(Project Loom)는 JVM이 관리하는 경량 스레드다. 블로킹 I/O를 만나면 OS 스레드를 붙잡지 않고 양보해, 수십만 개를 띄울 수 있다.

Thread.startVirtualThread(() -> { … });   // 스택이 힙에 저장되어 매우 가볍다

"스레드 풀로 동시성을 제한하던 이유가 사라진다" 는 것이 핵심 변화다. 다만 synchronized 블록 안에서 블로킹하면 여전히 OS 스레드를 붙든다(pinning) — ReentrantLock으로 바꿔야 한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 운영체제 — 프로세스/스레드·동기화·가상메모리