운영체제에서 프로세스(Process) 와 스레드(Thread) 는 프로그램이 실행되는 가장 기본적인 단위다. 개발자라면 이 둘의 차이와 구조를 이해하는 것이 매우 중요하며, 특히 병렬 프로그래밍이나 시스템 설계에 큰 영향을 미친다.

프로세스는 실행 중인 프로그램이다. 컴파일된 실행 파일(.exe, .out 등)이 메모리에 적재되어 CPU 자원을 받아 실제로 실행되면 프로세스가 된다.
운영체제는 각 프로세스에 다음과 같은 자원을 할당한다:
즉, 프로세스는 자원(Resource) 과 실행 상태(Context) 를 가진 독립적인 실행 단위다.
프로세스는 보통 다음과 같은 메모리 영역으로 구성된다:
| 영역 | 설명 |
|---|---|
| Text | 실행 코드가 위치한 영역 |
| Data | 초기화된 전역변수, static 변수 |
| BSS | 초기화되지 않은 전역변수 |
| Heap | 동적 메모리 할당 영역 (malloc, new 등) |
| Stack | 함수 호출 시 사용되는 지역변수 저장 영역 |
각 프로세스는 이 구조를 독립적으로 가지며, 다른 프로세스와 메모리를 공유하지 않는다.
스레드는 프로세스 내에서의 실행 흐름 단위다. 하나의 프로세스는 하나 이상의 스레드를 가질 수 있으며, 이들을 통해 멀티스레딩(Multithreading) 을 구현할 수 있다.
하나의 프로세스가 여러 작업을 동시에 처리해야 할 경우, 스레드를 나누어 병렬로 처리하면 성능이 향상된다.
| 항목 | 프로세스 | 스레드 |
|---|---|---|
| 정의 | 실행 중인 프로그램 | 실행 흐름 단위 |
| 메모리 공간 | 독립적 | 공유함 (코드, 데이터, 힙) |
| 생성 비용 | 높음 (Context Switching 포함) | 낮음 (Stack, Register만 분리) |
| 통신 방식 | IPC 필요 (파이프, 소켓 등) | 메모리 공유로 효율적 |
| 안정성 | 하나 죽어도 다른 프로세스는 영향 없음 | 하나가 죽으면 전체 프로세스 위험 |
실제 서버 프로그램에서는 요청을 처리하기 위해 보통 스레드 풀(Thread Pool) 을 만들어 동시성(concurrency)을 처리한다.
멀티스레드 환경에서는 여러 스레드가 동시에 같은 자원에 접근할 수 있기 때문에, 동기화가 필수적이다.
경쟁 상태(Race Condition) 를 방지하려면 락(Lock)을 사용해야 한다.
대표적인 동기화 도구:
적절한 동기화를 사용하지 않으면 데이터 손상, 데드락(Deadlock) 등이 발생할 수 있다.
| 함수 | 설명 |
|---|---|
fork() | 부모 프로세스를 복사하여 자식 프로세스를 생성 |
exec() | 현재 프로세스를 새로운 프로그램으로 덮어씀 |
wait() | 자식 프로세스의 종료를 기다림 |
exit() | 프로세스 종료 |
fork로 자식 프로세스를 만들고,exec로 새로운 프로그램을 실행하는 방식은 유닉스 계열에서 매우 일반적인 패턴이다.
C에서는 pthread 라이브러리를 통해 스레드를 생성할 수 있다.
#include <pthread.h>
void *thread_func(void *arg) {
// 실행할 코드
return NULL;
}
int main() {
pthread_t tid;
pthread_create(&tid, NULL, thread_func, NULL);
pthread_join(tid, NULL);
}