CS/컴퓨터공학 프로세스 vs 스레드 차이 총정리
✨ 개요
프로그램이 실행되면 프로세스(Process)가 만들어지고, 그 안에서 실제 일을 나눠 하는 흐름 단위가 스레드(Thread)입니다.
두 개념의 경계를 정확히 잡아두면 동시성 문제(데드락, 경쟁 조건)부터 성능 병목까지 훨씬 명확히 보입니다.
1. 요약
| 구분 | 프로세스 (Process) | 스레드 (Thread) |
|---|---|---|
| 정의 | 실행 중인 프로그램의 독립 실행 단위 | 프로세스 내부의 경량 실행 흐름 |
| 주소공간 | 분리됨(코드/데이터/힙/스택 각자 가짐) | 공유(코드/데이터/힙 공유, 스택은 개별) |
| 격리/안전 | 강함(다른 프로세스 메모리 직접 접근 불가) | 약함(같은 프로세스 내 공유 메모리로 인한 경쟁 위험) |
| 생성/스위칭 | 비용 큼(페이지 테이블/커널 구조체 교체) | 비용 작음(레지스터/스택 포인터 위주) |
| 통신 | IPC 필요(파이프, 소켓, 공유메모리 등) | 변수/컬렉션 등 메모리 공유 + 락/원자성 |
| 대표 사용 | 서로 다른 앱/서비스 | 한 작업의 병렬화, 비동기 I/O, UI+백그라운드 분업 |
2 메모리 구조와 공유 범위
├─ Code / Data / Heap ← 동일 프로세스의 모든 스레드가 공유
├─ Thread #1 ─ Stack1 ← 각 스레드는 자신의 스택(호출 프레임/지역변수)
├─ Thread #2 ─ Stack2
└─ Thread #n ─ StackN
- 공유: 전역 변수, 힙 객체, 파일 디스크립터(플랫폼별), 소켓 등
- 비공유: 스레드 스택, 일부 스레드 로컬 저장소(TLS)
결론: 스레드는 협업에 유리하지만 락·원자연산·메모리 가시성을 정확히 다뤄야 합니다.
3 컨텍스트 스위칭과 비용
3.1 프로세스 컨텍스트 스위치
- 교체 대상: 페이지 테이블(주소공간), 커널 구조체, 레지스터 세트
- 캐시/분기 예측기까지 교란 → 상대적으로 무거움
3.2 스레드 컨텍스트 스위치(동일 프로세스 내)
- 교체 대상: 레지스터, 스택 포인터, TCB 일부
- 주소공간은 유지 → 상대적으로 가벼움
실무 팁: I/O 대기 많은 워크로드는 스레드/비동기 I/O로 이득. 순수 CPU 바운드는 프로세스 분리(다중 코어 병렬)나 쓰레드+적절한 스케줄링/핀ning 등을 함께 고려.
4. PCB와 TCB (운영체제 관점 핵심)
- PCB (Process Control Block)
프로세스의 신분증/상태표. PID, 상태(RUNNING/READY/BLOCKED), 페이지 테이블 포인터, 파일 테이블, 신호/권한 등. - TCB (Thread Control Block)
스레드의 실행 맥락. 레지스터 스냅샷(PC, SP), 스케줄링 정보, 스레드 상태, 우선순위, TLS 포인터 등.
운영체제는 스케줄러가 PCB/TCB를 보고 누구를 언제 CPU에 태울지 결정합니다.
5. 동시성과 동기화의 필수 포인트
- 경쟁 조건(Race Condition): 공유 데이터에 동시 접근 → 불일치
- 상호 배제(Mutual Exclusion): 뮤텍스/세마포어/모니터/스핀락
- 원자성(Atomicity): CAS, 원자 변수(예: Java
AtomicInteger) - 메모리 가시성(Visibility): 언어/플랫폼의 메모리 모델(Java
volatile, Kotlin/JVM 동일), 배리어 - 교착상태(Deadlock): 상호배제·보유·비선점·환형대기 → 락 순서·타임아웃·재시도로 회피
6. 언제 무엇을 쓰나?
- 프로세스가 유리한 경우
- 강한 격리/안전 필요(보안 경계, 신뢰 차단)
- 서로 다른 런타임/라이브러리 충돌 방지(예: 확장 프로세스)
- 장애 격리(한쪽 크래시가 다른 쪽에 영향 X)
- 스레드가 유리한 경우
- 공유 상태가 필요한 협업(캐시, 오브젝트 풀)
- 맥락 전환 비용을 줄이고 싶을 때
- 많은 동시 I/O를 적은 리소스로 처리(네트워킹, UI+백그라운드 분업)
7. 실무 체크리스트
- “스레드는 항상 빠르다” → ❌ 락 경합/캐시 실드/컨텍션 폭증으로 느려질 수 있음
- “프로세스 간 데이터 공유 불가” → ❌ 공유 메모리/메모리 매핑으로 가능(단, 설계와 권한 필요)
- “코어 수만큼 스레드 생성” → ❌ I/O 비중, 블로킹 여부, 런타임 오버헤드를 함께 고려해야 최적
- Android: 앱 = 프로세스, 내부 컴포넌트(UI/백그라운드)는 스레드로 분업. 메인(UI) 스레드에서 블로킹 작업 금지 →
Handler,Coroutine(Dispatchers.IO),WorkManager사용. - JVM:
Thread,ExecutorService,ForkJoinPool, 코루틴(더 가벼운 실행 단위) 조합으로 동시성 모델 구성.