s-nova 님의 블로그
프로세스, 스레드 본문
멀티스레드 프로그래밍을 이해하려면 먼저 프로그램, 프로세스, 스레드, 코어가 각각 무엇인지, 그리고 이들이 어떻게 맞물려 돌아가는지를 정확히 알아야 합니다.
1. 핵심 개념 정리
| 개념 | 설명 |
| 프로그램$^{\text{Program}}$ | 저장장치에 있는 실행 가능한 파일 또는 명령들의 묶음. 아직 실행되지 않은 정적인 상태. |
| 프로세스$^{\text{Process}}$ | 프로그램을 실행하면 메모리에 올라가 실제로 실행 중인 인스턴스가 된 상태. 하나의 프로그램을 여러 번 실행하면 각각 독립된 프로세스가 생성된다. |
| 스레드$^{\text{Thread}}$ | 프로세스 안에서 실제로 CPU를 타고 도는 실행 흐름의 단위. 하나의 프로세스는 하나 이상의 스레드를 가진다. |
| 코어$^{\text{Core}}$ | CPU 안에 있는 연산 장치. 코어가 여러 개면 진정한 병렬 실행이 가능하다. |
2. 스레드의 메모리 구조
같은 프로세스 안의 스레드들은 메모리의 일부를 공유하고, 일부는 독립적으로 가집니다.
| 영역 | 공유 여부 | 내용 |
| 코드$^{\text{Code}}$ 영역 | 스레드 간 공유 | 실행할 기계어 명령어 |
| 데이터$^{\text{Data}}$ 영역 | 스레드 간 공유 | 전역 변수, 정적 변수 |
| 힙$^{\text{Heap}}$ 영역 | 스레드 간 공유 | 동적 할당 메모리 |
| 스택$^{\text{Stack}}$ 영역 | 스레드마다 독립 | 지역 변수, 함수 호출 정보 |
공유 영역 덕분에 스레드 간 협업이 빠르지만, 동기화를 잘못하면 여러 스레드가 동시에 같은 데이터를 수정하는 문제가 발생합니다. 힙과 데이터 영역에 접근할 때 특히 주의가 필요합니다.
3. CPU 스케줄링과 동시성
코어가 하나뿐인 CPU는 한 순간에 하나의 스레드만 실행할 수 있습니다. 그렇다면 어떻게 여러 작업이 동시에 돌아가는 것처럼 보일까요?
운영체제의 스케줄러$^{\text{Scheduler}}$가 매우 짧은 시간마다 실행할 스레드를 바꿔끼웁니다. 이 전환이 너무 빠르기 때문에 사용자 눈에는 여러 작업이 동시에 실행되는 것처럼 보입니다. 이를 동시성$^{\text{Concurrency}}$이라고 합니다.
📌 동시성 vs 병렬성
동시성$^{\text{Concurrency}}$: 코어가 하나여도 스레드를 빠르게 교체하여 동시에 실행되는 것처럼 보이는 것
병렬성$^{\text{Parallelism}}$: 코어가 여러 개여서 실제로 여러 스레드가 동시에 실행되는 것
4. 컨텍스트 스위칭
스케줄러가 실행 스레드를 바꿀 때 일어나는 작업이 컨텍스트 스위칭$^{\text{Context Switching}}$입니다.
- 현재 스레드 $($A$)$의 상태를 저장 — 레지스터 값, 프로그램 카운터$^{\text{PC}}$ $($어디까지 실행했는지$)$, 스택 포인터 등
- 다음 스레드 $($B$)$의 저장된 상태를 복원
- CPU가 B를 이어서 실행
이 과정 자체에도 비용이 발생합니다. 전환이 너무 잦으면 실제 작업보다 상태 저장/복원에 더 많은 시간을 쓰게 되고, CPU 캐시가 무효화$^{\text{Cache Miss}}$되어 성능이 오히려 떨어질 수 있습니다.
5. 멀티프로세스 vs 멀티스레드
여러 작업을 동시에 처리하는 방법에는 두 가지가 있습니다.
| 항목 | 멀티프로세스$^{\text{Multi-Process}}$ | 멀티스레드$^{\text{Multi-Thread}}$ |
| 메모리 구조 | 프로세스마다 독립된 메모리 공간 | 힙/데이터/코드 영역 공유 |
| 통신 방법 | IPC$^{\text{Inter-Process Communication}}$ 필요 $($느림$)$ | 공유 메모리로 직접 접근 $($빠름$)$ |
| 안정성 | 한 프로세스 죽어도 다른 프로세스에 영향 없음 | 한 스레드 오작동이 전체 프로세스에 영향 |
| 컨텍스트 스위칭 비용 | 큼 $($메모리 공간 자체를 교체$)$ | 작음 $($스택만 교체$)$ |
| 동기화 필요성 | 낮음 | 높음 $($Race Condition 주의$)$ |
💡 게임 서버 관점: 게임 서버는 수많은 클라이언트를 동시에 처리해야 하므로 일반적으로 멀티스레드를 활용합니다. 공유 메모리로 빠른 데이터 접근이 가능하지만, 그만큼 Race Condition$^{\text{경쟁 조건}}$과 Deadlock$^{\text{교착 상태}}$에 주의한 동기화 설계가 필요합니다.
'CS' 카테고리의 다른 글
| [네트워크] TCP vs UDP (0) | 2025.08.17 |
|---|---|
| [운영체제] 메모리 구조 $($코드, 데이터, 스택, 힙$)$ (0) | 2025.08.03 |
| 스택 메모리 (0) | 2025.01.02 |