
웹 서버가 요청 세 개를 동시에 처리해야 한다고 해봅니다. 가장 단순한 방법은 같은 프로그램을 프로세스 세 개로 띄우는 것입니다.
그런데 세 프로세스는 코드가 완전히 같습니다. 읽는 설정 데이터도 같습니다. 다른 것은 "지금 어느 줄을 실행 중인지"와 "함수 호출이 어디까지 쌓였는지"뿐입니다. 그런데도 프로세스마다 주소 공간과 PCB를 통째로 따로 가지므로 메모리가 낭비되고, CPU를 넘길 때마다 무거운 문맥 교환이 일어납니다.
그래서 같은 것은 같이 쓰고, 다른 것만 따로 갖자는 발상이 나옵니다. 이것이 스레드(thread)입니다.
스레드는 CPU 이용의 기본 단위입니다. 프로세스 안에서 CPU를 받아 실제로 명령을 수행하는 흐름 하나를 말합니다.
| 구분 | 항목 | 이유 |
|---|---|---|
| 공유 | code, data, OS resources (열린 파일 등) | 같은 프로그램이므로 같이 써도 됨 |
| 스레드마다 따로 | program counter, register, stack | 실행 위치와 함수 호출 이력이 각자 다름 |
스레드들이 공유하는 부분, 즉 code, data, OS resources를 묶어 task라고 부릅니다. 이 관점에서 보면 기존의 프로세스는 스레드를 하나만 가진 task입니다.

스레드마다 PC와 register를 따로 가지므로 PCB 안에도 이 부분만 스레드 수만큼 늘어납니다. 같은 task 안의 스레드끼리 CPU를 넘길 때는 주소 공간을 바꿀 필요가 없어 문맥 교환보다 훨씬 가볍습니다.
앞의 웹 서버를 수치로 비교합니다. 코드 20MB, 데이터 80MB, 스택 1MB라고 가정합니다.
다중 스레드(multi-thread)를 쓰면 처리 속도가 빨라지고 성능이 향상됩니다. 이를 네 가지로 나눠 봅니다.
| 장점 | 의미 | 예 |
|---|---|---|
| 응답성 (responsiveness) | 한 스레드가 막혀도 다른 스레드가 사용자에게 계속 반응 | 브라우저가 이미지를 받는 동안 텍스트를 먼저 표시 |
| 자원 공유 (resource sharing) | code, data, 자원을 같이 써서 협력이 쉬움 | 같은 설정 데이터를 여러 요청 처리에서 공유 |
| 경제성 (economy) | 생성과 전환 비용이 프로세스보다 작음 | 위 예제의 303MB 대 103MB |
| 멀티프로세서 활용 (utilization of MP architectures) | 스레드마다 다른 CPU에서 병렬 실행 가능 | 코어 4개에 스레드 4개를 동시에 실행 |
응답성은 CPU가 하나여도 얻을 수 있고, 멀티프로세서 활용은 CPU가 여러 개일 때만 얻을 수 있다는 점이 다릅니다.
스레드를 누가 관리하느냐에 따라 둘로 나뉩니다.
| 구분 | 커널 스레드 (kernel thread) | 유저 스레드 (user thread) |
|---|---|---|
| 관리 주체 | 커널 | 사용자 수준 라이브러리 |
| 커널이 스레드를 아는가 | 안다 | 모른다 (프로세스 하나로만 봄) |
| 스레드 전환 | 커널이 스케줄링 | 라이브러리가 전환, 커널 진입 없음 |
| 전환 비용 | 상대적으로 큼 | 작음 |
| 한 스레드가 I/O로 막히면 | 그 스레드만 막힘 | 프로세스 전체가 막힘 |
유저 스레드는 커널을 거치지 않아 가볍지만, 커널 입장에서는 스레드가 여러 개인지 모르므로 생기는 한계가 있습니다.