[OS] Process์ Thread
๐งฉ Process
ํ๋ ์ด์์ฒด์ ์ ๊ฐ์ฅ ๊ฑฐ๋ํ ๋ง๋ฒ์ โ๋ ์ ์ ํ์โ์ ๋ง๋ค์ด๋ด๋ ๋ฐ ์์ต๋๋ค. ์์ญ ๊ฐ์ ์ฑ์ด ๋์์ ๋์๊ฐ๊ณ ์์์๋, ๊ฐ ํ๋ก๊ทธ๋จ์ ๋ง์น ์์ ์ด CPU ์ ์ฒด๋ฅผ ์ ์ ํ๊ณ ๋ฌดํํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ๋ก ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ํ๋ํฉ๋๋ค. ์ด์์ฒด์ ๋ ์ด ๊ฐ๋ จํ๊ณ ์ด๊ธฐ์ ์ธ ํ๋ก๊ทธ๋จ๋ค์๊ฒ Process๋ผ๋ ์ถ์ํ๋ ๋ฌด๋๋ฅผ ์ ๊ณตํจ์ผ๋ก์จ ์ด ํ์์ ํ์ค๋ก ๋ง๋ญ๋๋ค. ํ๋ก์ธ์ค๋ ๋จ์ํ ์คํ ์ค์ธ ํ๋ก๊ทธ๋จ์ ๋์ด ํ๋์จ์ด ์์์ ์์ ํ๊ฒ ๊ณต์ ํ๊ธฐ ์ํด ์ค๊ณ๋ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๊ฒฉ๋ฆฌ ๋จ์์ ๋๋ค.
์ด์์ฒด์ ์ ๊ฒฉ๋ฆฌ ์ค๊ณ์ ์ฃผ์ ๊ณต๊ฐ
ํ๋ก์ธ์ค๊ฐ ์์ฑ๋๋ ์๊ฐ, ์ด์์ฒด์ ๋ ํด๋น ํ๋ก์ธ์ค๋ง์ ์ํ ๊ฐ์ ์ธ๊ณ์ธ โ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ(Virtual Address Space)โ์ ํ ๋นํฉ๋๋ค. ์ด ๊ณต๊ฐ์ ํฌ๊ฒ ๋ค ๊ฐ์ง ์์ญ์ผ๋ก ๋๋ฉ๋๋ค. ์คํ๋ ๊ธฐ๊ณ์ด ์ฝ๋๊ฐ ๋ด๊ธด Text, ์ ์ญ ๋ณ์์ ์ ์ ๋ฐ์ดํฐ๊ฐ ์์นํ Data, ๋์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ์ผ์ด๋๋ Heap, ๊ทธ๋ฆฌ๊ณ ํจ์ ํธ์ถ ์ ๋ณด์ ์ง์ญ ๋ณ์๋ฅผ ์ ์ฅํ๋ Stack์ ๋๋ค.
์ด ์ค๊ณ์ ํต์ฌ์ โ๋ณดํธโ์ ์์ต๋๋ค. A ํ๋ก์ธ์ค๋ B ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ์ ์ง์ ๋ค์ฌ๋ค๋ณผ ์ ์์ต๋๋ค. ๋ง์ฝ ์ด๋ค ํ๋ก์ธ์ค๊ฐ ์์ ์๊ฒ ํ ๋น๋์ง ์์ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์นจ๋ฒํ๋ ค ํ๋ฉด, ํ๋์จ์ด(MMU)์ ์ด์์ฒด์ ๋ ์ฆ์ ์ด๋ฅผ ์ฐจ๋จํ๊ณ โSegmentation Faultโ๋ผ๋ ์์คํ ๊ฒฝ๊ณ ์ ํจ๊ป ํ๋ก์ธ์ค๋ฅผ ์ข ๋ฃ์ํต๋๋ค. ์ด๋ฌํ ์๊ฒฉํ ๊ฒฉ๋ฆฌ๋ ํ ํ๋ก์ธ์ค์ ํฌ๋์๊ฐ ์์คํ ์ ์ฒด์ ๋ถ๊ดด๋ก ์ด์ด์ง๋ ๊ฒ์ ๋ฐฉ์งํ๋ ๋ฐฉํ๋ฒฝ ์ญํ ์ ํฉ๋๋ค.
ํ๋ก์ธ์ค ์ ์ด ๋ธ๋ก(PCB)์ ๊ตฌ์กฐ์ ์ญํ
์ด์์ฒด์ ๋ ์๋ง์ ํ๋ก์ธ์ค๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด ๊ฐ ํ๋ก์ธ์ค์ ๋ชจ๋ ์ ๋ณด๋ฅผ ๊ธฐ๋กํ ์ผ์ข ์ โ์ ๋ถ์ฆโ์ ๋ง๋ญ๋๋ค. ์ด๋ฅผ PCB(Process Control Block)๋ผ๊ณ ๋ถ๋ฆ ๋๋ค. ์ปค๋์ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ ์ฅ๋๋ ์ด ๊ตฌ์กฐ์ฒด๋ ํ๋ก์ธ์ค๊ฐ ์ ์ ๋ฉ์ท๋ค๊ฐ ๋ค์ ์คํ๋ ๋, ์ด์ ์ ์ํ๋ฅผ ์๋ฒฝํ๊ฒ ๋ณต์ํ๊ธฐ ์ํ ๋ชจ๋ ๋จ์๋ฅผ ๋ด๊ณ ์์ต๋๋ค.
PCB์๋ ๋ค์๊ณผ ๊ฐ์ ํต์ฌ ๋ฐ์ดํฐ๋ค์ด ํฌํจ๋ฉ๋๋ค.
- PID (Process Identifier): ์์คํ ๋ด์์ ํ๋ก์ธ์ค๋ฅผ ์๋ณํ๋ ์ ์ผํ ๋ฒํธ.
- Process State: ์์ฑ(New), ์ค๋น(Ready), ์คํ(Running), ๋๊ธฐ(Waiting), ์ข ๋ฃ(Terminated) ์ค ํ์ฌ ์ํ.
- Program Counter (PC): ์ด ํ๋ก์ธ์ค๊ฐ ๋ค์์ ์คํํ ๋ช ๋ น์ด์ ์ฃผ์.
- CPU Registers: ๋์ฐ๊ธฐ, ์ธ๋ฑ์ค ๋ ์ง์คํฐ ๋ฑ ํ์ฌ CPU ๋ด๋ถ์ ๋ฌผ๋ฆฌ์ ์ธ ์ํ๊ฐ.
- Memory Management Information: ํ์ด์ง ํ ์ด๋ธ์ด๋ ์ธ๊ทธ๋จผํธ ํ ์ด๋ธ ๋ฑ ๋ฉ๋ชจ๋ฆฌ ๋งคํ ์ ๋ณด.
ํ๋ก์ธ์ค์ ์๋ช ์ฃผ๊ธฐ์ fork() ย
์ ๋์ค ๊ณ์ด ์์คํ ์์ ์๋ก์ด ํ๋ก์ธ์ค๋
fork()์์คํ ์ฝ์ ํตํด ๋ถ๋ชจ ํ๋ก์ธ์ค๋ฅผ ๊ทธ๋๋ก ๋ณต์ฌํ๋ฉฐ ํ์ํฉ๋๋ค. ์ด๋ ์์ ํ๋ก์ธ์ค๊ฐ ๋ถ๋ชจ์ PCB ์ ๋ณด์ ๋ฉ๋ชจ๋ฆฌ ์ํ๋ฅผ ๊ณ ์ค๋ํ ๋ฌผ๋ ค๋ฐ๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid;
printf("fork() ํธ์ถ ์ . (๋ถ๋ชจ PID: %d)\n", getpid());
// ์๋ก์ด ํ๋ก์ธ์ค ์์ฑ (๋ถ๋ชจ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ ๋ณต์ )
pid = fork();
if (pid < 0) {
// fork ์คํจ
fprintf(stderr, "fork failed\n");
return 1;
} else if (pid == 0) {
// ์์ ํ๋ก์ธ์ค ์ฝ๋ ์์ญ
// ์์์๊ฒ fork์ ๋ฐํ๊ฐ์ 0์
๋๋ค.
printf("์ ๋ ์์ ํ๋ก์ธ์ค์
๋๋ค. (PID: %d, ๋ถ๋ชจ PID: %d)\n", getpid(), getppid());
} else {
// ๋ถ๋ชจ ํ๋ก์ธ์ค ์ฝ๋ ์์ญ
// ๋ถ๋ชจ์๊ฒ fork์ ๋ฐํ๊ฐ์ ์์ฑ๋ ์์์ PID์
๋๋ค.
printf("์ ๋ ๋ถ๋ชจ ํ๋ก์ธ์ค์
๋๋ค. (PID: %d, ์์ PID: %d)\n", getpid(), pid);
}
// ๋ถ๋ชจ์ ์์ ๋ชจ๋ ์ด ์ฝ๋๋ฅผ ์คํํ์ง๋ง, ๊ฐ์์ ์ฃผ์ ๊ณต๊ฐ์์ ์คํ๋ฉ๋๋ค.
printf("ํ๋ก์ธ์ค ์ข
๋ฃ. (PID: %d)\n", getpid());
return 0;
}
์ปจํ ์คํธ ์ค์์นญ์ ๋ก์ฐ๋ ๋ฒจ ๋ฉ์ปค๋์ฆ
ํ๋์ CPU ์ฝ์ด๋ ํ์๊ฐ์ ๋จ ํ๋์ ๋ช ๋ น์ด๋ง ์คํํ ์ ์์ต๋๋ค. ๊ทธ๋ผ์๋ ์ฐ๋ฆฌ๊ฐ ์ฌ๋ฌ ์ฑ์ ๋์์ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ๋๋ผ๋ ์ด์ ๋ ์ด์์ฒด์ ๊ฐ ์ ๋ฐ๋ฆฌ์ด(ms) ๋จ์๋ก ํ๋ก์ธ์ค๋ฅผ ๊ฐ์์น์ฐ๋ ์ปจํ ์คํธ ์ค์์นญ(Context Switching)์ ์ํํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด ๊ณผ์ ์ ์๊ฐ๋ณด๋ค ํจ์ฌ ๋ฌด๊ฒ๊ณ ์ ๊ตํ ์๋ฌด๋ฅผ ํ์๋ก ํฉ๋๋ค.
- ์ธํฐ๋ฝํธ ๋ฐ์: ํ์ด๋จธ ์ธํฐ๋ฝํธ ๋ฑ์ด ๋ฐ์ํ์ฌ ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค์ ์ ์ด๊ถ์ด ์ปค๋๋ก ๋์ด๊ฐ๋๋ค.
- ์ํ ์ ์ฅ: ํ์ฌ CPU์ ๋จ์์๋ ๋ ์ง์คํฐ ๊ฐ๋ค(PC, SP ๋ฑ)์ ํ์ฌ ์คํ ์ค์ธ ํ๋ก์ธ์ค์ PCB์ ์์ ํ๊ฒ ์ ์ฅํฉ๋๋ค.
- ๋ค์ ํ๋ก์ธ์ค ์ ํ: ์ค์ผ์ค๋ฌ๊ฐ ๋ค์์ ์คํํ ํ๋ก์ธ์ค๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
- ์ํ ๋ณต์: ์ ํ๋ ํ๋ก์ธ์ค์ PCB์์ ์ด์ ์ ์ ์ฅํด๋์๋ ๋ ์ง์คํฐ ๊ฐ๋ค์ CPU๋ก ๋ค์ ๋ก๋ํฉ๋๋ค.
- ์ ์ ๋ชจ๋ ์ ํ: ์ปค๋์ ์ ์ด๊ถ์ ํ๋ก์ธ์ค์๊ฒ ๋๊ธฐ๊ณ , ํ๋ก์ธ์ค๋ ๋ง์น ๋ฉ์ถ ์ ์์๋ค๋ ๋ฏ์ด ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํฉ๋๋ค.
์ด ๊ณผ์ ์์ CPU๋ ์ ์๋ฏธํ ์ฐ์ฐ์ ํ์ง ๋ชปํฉ๋๋ค. ์ฆ, ์ปจํ ์คํธ ์ค์์นญ์ ๋ฉํฐํ์คํน์ ์ํ ํ์์ ์ธ ์ง์ถ์ด์ง๋ง, ๋์์ ์์คํ ์ฑ๋ฅ์ ๊ฐ์๋จน๋ โ์์ ์ค๋ฒํค๋โ์ด๊ธฐ๋ ํฉ๋๋ค.
๐งฉ Thread
ํ๋ก์ธ์ค๊ฐ ๋ ๋ฆฝ๋ ์ ๋ ฅ๊ณผ ๋ณด์ ์์ค์ ๊ฐ์ถ ๊ฑฐ๋ํ โ๊ณต์ฅ ๋ถ์งโ๋ผ๋ฉด, Thread๋ ๊ทธ ๊ณต์ฅ ์์์ ๋ฐ์ ์์ง์ด๋ โ์๋ จ๋ ์์ ์โ์ ๋๋ค. ํ๋์ ํ๋ก์ธ์ค๋ผ๋ ์ธํ๋ฆฌ ์์์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์์ ์ ์ํํ๋ฉฐ, ์ด๋ค์ ๊ณต์ฅ์ ์์ฌ ์ฐฝ๊ณ (Heap)์ ์ค๊ณ๋(Text/Data)๋ฅผ ํจ๊ป ์ฌ์ฉํฉ๋๋ค. ์ด๋ฌํ ์์ ๊ณต์ ๋๋ถ์ ์ค๋ ๋๋ ํ๋ก์ธ์ค๋ณด๋ค ํจ์ฌ ๊ฐ๋ณ๊ณ ๋น ๋ฅด๊ฒ ์์ฑ๋๋ฉฐ, ๋ฐ์ดํฐ ๊ตํ ๋ํ ๋ณต์กํ ํต์ ๊ณผ์ ์์ด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ์ฝ๋ ๊ฒ๋ง์ผ๋ก ๊ฐ๋ฅํด์ง๋๋ค.
์คํ ํ๋ฆ์ ๊ณต์ ์ ๊ฒฉ๋ฆฌ
์ค๋ ๋์ ๋ณธ์ง์ โ์คํ ํ๋ฆ์ ๋ถ๋ฆฌโ์ ์์ต๋๋ค. ๋ชจ๋ ์ค๋ ๋๋ ์์๋ ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ์ ๊ณต์ ํ์ง๋ง, ๊ฐ์๊ฐ โ์ด๋๊น์ง ์ฝ๋๋ฅผ ์ฝ์๋์งโ์ โํ์ฌ ๊ณ์ฐ ์ค์ธ ์์ ๊ฐโ์ ์ฒ ์ ํ ๋ถ๋ฆฌ๋์ด์ผ ํฉ๋๋ค.
์ค๋ ๋ ๊ฐ์ ๊ณต์ ๋๋ ๊ฒ๊ณผ ๊ฒฉ๋ฆฌ๋๋ ๊ฒ์ ๊ตฌ๋ถ์ ๋ฉํฐํ์คํน์ ์ฑ๋ฅ๊ณผ ์์ ์ฑ์ ๊ฒฐ์ ์ง๋ ํต์ฌ ์ค๊ณ์ ๋๋ค.
- ๊ณต์ ์์ญ: ์ฝ๋(Text), ์ ์ญ ๋ณ์(Data), ๋์ ํ ๋น ๋ฉ๋ชจ๋ฆฌ(Heap), ์ด๋ฆฐ ํ์ผ ํธ๋ค ๋ฑ ํ๋ก์ธ์ค์ ์์.
- ๊ฒฉ๋ฆฌ ์์ญ: ๊ฐ ์ค๋ ๋๋ง์ ๋ ๋ฆฝ์ ์ธ ์คํ(Stack)๊ณผ ๋ ์ง์คํฐ ์งํฉ(Program Counter ๋ฑ).
์ด๋ฌํ ๊ตฌ์กฐ ๋๋ถ์ ์ค๋ ๋ ๊ฐ์ ์ ํ์ ํ๋ก์ธ์ค ์ ํ๋ณด๋ค ๋น์ฉ์ด ํจ์ฌ ์ ๋ ดํฉ๋๋ค. ํ์ด์ง ํ ์ด๋ธ์ ํต์งธ๋ก ๊ฐ์์น์ธ ํ์ ์์ด CPU ๋ ์ง์คํฐ ๊ฐ๋ง ์ด์ง ๋ฐ๊ฟ์ฃผ๋ฉด ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ค๋ ๋ ์ ์ด ๋ธ๋ก(TCB)๊ณผ ์คํ ํ ๋น
์ด์์ฒด์ ์ ์ฅ์์ ์ค๋ ๋๋ โ์ค์ผ์ค๋ง์ ์ต์ ๋จ์โ์ ๋๋ค. ์ปค๋์ ํ๋ก์ธ์ค๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด PCB๋ฅผ ๋๋ฏ, ์ค๋ ๋๋ฅผ ๊ด๋ฆฌํ๊ธฐ ์ํด TCB(Thread Control Block)๋ฅผ ์ ์งํฉ๋๋ค. TCB๋ PCB์ ์์ ๊ฒฉ์ธ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ก, ํด๋น ์ค๋ ๋์ ์คํ ์ํ, CPU ๋ ์ง์คํฐ ๊ฐ, ๊ทธ๋ฆฌ๊ณ ์คํ ํฌ์ธํฐ๋ฅผ ๊ธฐ๋กํฉ๋๋ค.
์ฌ๊ธฐ์ ๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ์ง์ ์ ์คํ(Stack)์ ๋ฐฐ์น์ ๋๋ค. ์ค๋ ๋๊ฐ ์์ฑ๋ ๋๋ง๋ค ์ด์์ฒด์ ๋ ํด๋น ์ค๋ ๋๋ง์ ์ํ ์ ์ฉ ์คํ ๊ณต๊ฐ์ ํ๋ก์ธ์ค์ ์ฃผ์ ๊ณต๊ฐ ๋ด์ ํ ๋นํฉ๋๋ค. ์ด ๊ณต๊ฐ์ ํจ์ ํธ์ถ ์์ ์ง์ญ ๋ณ์์ ๋ณต๊ท ์ฃผ์๋ฅผ ์ ์ฅํ๋ฉฐ, ์ค๋ ๋ ๊ฐ์ ์คํ ํ๋ฆ์ด ๋ค์์ด์ง ์๋๋ก ๋ณด์ฅํ๋ ์ตํ์ ๋ณด๋ฃจ๊ฐ ๋ฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// ๋ชจ๋ ์ค๋ ๋๊ฐ ๊ณต์ ํ๋ ์ ์ญ ๋ณ์ (Data ์์ญ)
int shared_counter = 0;
// ์ค๋ ๋๊ฐ ์คํํ ํจ์
void *thread_function(void *arg) {
char *thread_name = (char *)arg;
int i;
// ๊ฐ ์ค๋ ๋๋ ์์ ๋ง์ ์คํ์ ์ง์ญ ๋ณ์ i๋ฅผ ๊ฐ์ง๋๋ค.
for (i = 0; i < 1000000; i++) {
// ๊ณต์ ๋ณ์์ ๋์ ์ ๊ทผ (๊ฒฝ์ ์ํ ๋ฐ์ ๊ฐ๋ฅ)
shared_counter++;
}
printf("%s ์์
์๋ฃ.\n", thread_name);
return NULL;
}
int main() {
pthread_t thread1, thread2;
// ๋ ๊ฐ์ ์ค๋ ๋ ์์ฑ
// ๊ฐ ์ค๋ ๋๋ thread_function์ ์คํํ๋ฉฐ, ๋์ผํ shared_counter๋ฅผ ๊ณต์ ํฉ๋๋ค.
pthread_create(&thread1, NULL, thread_function, "Thread 1");
pthread_create(&thread2, NULL, thread_function, "Thread 2");
// ์ค๋ ๋๊ฐ ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐ (๋ฉ์ธ ์ค๋ ๋ ๋ธ๋กํน)
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// ๊ฒฐ๊ณผ ์ถ๋ ฅ (๋๊ธฐํ๊ฐ ์๋ค๋ฉด 2000000์ด ์๋ ์ ์์)
printf("์ต์ข
์นด์ดํฐ ๊ฐ: %d\n", shared_counter);
return 0;
}
๋ฉํฐ์ค๋ ๋ฉ์ ๋น์ฉ๊ณผ ๊ฒฝ์ ์ํ
๊ณต์ ์ ํธ๋ฆฌํจ ๋ค์๋ โ๋๊ธฐํโ๋ผ๋ ํน๋ ํ ๋๊ฐ๊ฐ ๋ฐ๋ฆ ๋๋ค. ์ฌ๋ฌ ์์ ์๊ฐ ํ๋์ ์์ฌ ์ฐฝ๊ณ ์์ ๋์์ ๋ฌผ๊ฑด์ ๊บผ๋ด๋ ค ํ ๋ ์ถฉ๋์ด ๋ฐ์ํ๋ฏ, ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ๊ฒฝ์ ์ํ(Race Condition)๊ฐ ํ์ฐ์ ์ผ๋ก ๋ฐ์ํฉ๋๋ค.
์๋ง ๋ช ์ ์ฌ์ฉ์๊ฐ ๋์์ ์ ๊ทผํ๋ ๊ณ ๋ถํ ์์คํ ์์ ๋ฐ์ดํฐ ์ ํฉ์ฑ์ ์ ์งํ๋ ๊ฒ์ ๋๋จํ ์ด๋ ค์ด ๊ณผ์ ์ ๋๋ค. ํ ์ค๋ ๋๊ฐ ๊ณต์ ๋ณ์๋ฅผ ์ฝ๊ณ ์์ ํ๋ ค๋ ์ฐฐ๋์ ์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๊ฐ์ ๋ฐ๊ฟ๋ฒ๋ฆฌ๋ฉด, ์์คํ ์ ๋ ผ๋ฆฌ์ ํ๊ตญ์ ์ง๋ฉดํฉ๋๋ค.
์ ๊ธ ์ฅ์น์ ๋ณ๋ ฌ์ฑ ์ ํ
์ค๋ ๋ ์์ ์ฑ(Thread Safety)์ ํ๋ณดํ๊ธฐ ์ํด ๋ฎคํ ์ค(Mutex)๋ ์ธ๋งํฌ์ด(Semaphore) ๊ฐ์ ์ ๊ธ ์ฅ์น๋ฅผ ์ฌ์ฉํ๋ฉด, ์์ด๋ฌ๋ํ๊ฒ๋ ์ค๋ ๋์ ์ต๋ ์ฅ์ ์ธ โ๋ณ๋ ฌ์ฑโ์ด ํผ์๋ฉ๋๋ค. ์์์ ๊ธฐ๋ค๋ฆฌ๋ ์ค๋ ๋๋ค์ด ์ค์ ์๊ฒ ๋๋ฉด์ CPU๋ ๋๊ฒ ๋๊ณ , ์ ์ฒด ์ฒ๋ฆฌ๋์ ๊ธ๊ฐํ๋ โ์ ๊ธ ๊ฒฝํฉ(Lock Contention)โ ํ์์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ฒฐ๊ตญ ์์ง๋์ด๋ง์ ํต์ฌ์ โ์ผ๋ง๋ ๋ง์ ์ค๋ ๋๋ฅผ ๋ง๋๋๋โ๊ฐ ์๋๋ผ, โ๊ณต์ ์์์ ์ต์ํํ๋ฉด์ ์ด๋ป๊ฒ ํจ์จ์ ์ผ๋ก ์ค์ผ์ค๋งํ๋๋โ์ ๋ฌ๋ ค ์์ต๋๋ค.
Cache Pollution
์ปจํ ์คํธ ์ค์์นญ์ ์ง์ง ๋น์ฉ์ ๋จ์ํ CPU ๋ ์ง์คํฐ๋ฅผ ์ ์ฅํ๊ณ ๋ณต์ํ๋ ์ ๋ง์ดํฌ๋ก์ด(ฮผs)์ ์๊ฐ์๋ง ์์ง ์์ต๋๋ค. ์ง์ ์ผ๋ก ๋ผ์ํ ์์ค์ ํ๋ก์ธ์ค๊ฐ ๊ต์ฒด๋ ์งํ, CPU๊ฐ ํ๋์ โ๋ฉ์ฒญํด์ง๋โ ํ์์์ ๋ฐ์ํฉ๋๋ค. ์ด๋ฅผ Cache Pollution(์บ์ ์ค์ผ)์ด๋ผ ๋ถ๋ฆ ๋๋ค. ์ด๋ ๋ง์น ๋ณต์กํ ์ค๊ณ๋๋ฅผ ์ฑ ์ ๊ฐ๋ ํผ์ณ๋๊ณ ์์ ํ๋ ์์ง๋์ด๊ฐ, ๊ฐ์ ๋ก ์๋ฆฌ๋ฅผ ๋น์ ๋ค ๋์์์ ๋ ์ด์ง๋ฌ์ง ์ฑ ์ ์์์ ๋ค์ ํ์ํ ๋๊ตฌ๋ฅผ ์ฐพ๋ ๋ฐ ํ์ฐธ์ ์๋ชจํ๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
CPU ์บ์ ๊ณ์ธต๊ณผ ๋ก์ปฌ๋ฆฌํฐ์ ๋ถ๊ดด
ํ๋ CPU๋ ์ฃผ ๋ฉ๋ชจ๋ฆฌ(RAM)์ ๋๋ฆฐ ์๋๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด L1, L2, L3๋ก ์ด์ด์ง๋ ์ ๊ตํ ์บ์ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค. ํ๋ก์ธ์ค๊ฐ ์คํ๋๋ ๋์, CPU๋ โ์ฐธ์กฐ ๊ตญ์์ฑ(Locality of Reference)โ ์๋ฆฌ์ ๋ฐ๋ผ ์์ฃผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ์ ๋ช ๋ น์ด๋ฅผ ์ด ๋น ๋ฅธ ์บ์์ ๊ฐ๋ ์ฑ์๋ก๋๋ค. ์ด ์ํ๋ฅผ ํํ ์บ์๊ฐ โ์์ด(Warm-up)โ๋์๋ค๊ณ ํํํฉ๋๋ค.
ํ์ง๋ง ์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋๋ ์๊ฐ, ์๋กญ๊ฒ ๋ค์ด์จ ํ๋ก์ธ์ค๋ ๊ธฐ์กด ํ๋ก์ธ์ค๊ฐ ์ ์จ ์์๋ ์บ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ด๋ด๊ณ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ์ฑ์ฐ๊ธฐ ์์ํฉ๋๋ค. ์ด ๊ณผ์ ์์ ๊ธฐ์กด ํ๋ก์ธ์ค์ โ์ํน ์ (Working Set)โ์ ํ๊ดด๋ฉ๋๋ค. ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ๊ธฐ๋ฒ์ด ๋ฐ์ดํฐ ๋ณต์ฌ ๋น์ฉ์ ์ค์ฌ์ฃผ์์์ง์ธ์ ํ๋์จ์ด ์บ์์ ๋ฌผ๋ฆฌ์ ์ธ ์ค์ผ๊น์ง๋ ๋ง์ง ๋ชปํฉ๋๋ค.
์ปจํ ์คํธ ์ค์์นญ์ด ๋จ๊ธฐ๋ ์ฑ๋ฅ ๋ถ์ฑ
์บ์ ์ค์ผ์ ํ๋ก์ธ์ค๊ฐ ๋ค์ ์คํ๋ ๋ โ์บ์ ๋ฏธ์ค(Cache Miss)โ์ ํญ๋ฐ์ ์ธ ์ฆ๊ฐ๋ก ์ด์ด์ง๋๋ค. CPU๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ธฐ ์ํด ์บ์๋ณด๋ค ์๋ฐฑ ๋ฐฐ ๋๋ฆฐ RAM๊น์ง ์ง์ ์ฐพ์๊ฐ์ผ ํ๋ฉฐ, ์ด ๊ธฐ๊ฐ ๋์ ํ๋ก์ธ์ค์ ์ฐ์ฐ ์๋๋ ํ์์ ์๋ถ์ ์ผ ์์ค์ผ๋ก ๊ณค๋๋ฐ์ง์นฉ๋๋ค.
ํนํ ๊ณ ๋ถํ ํ๊ฒฝ์์๋ ๋ฏธ์ธํ ๋ ์ดํด์ ์ฆ๊ฐ๊ฐ ์ ์ฒด ์ฒ๋ฆฌ๋์ ๊ธ๊ฒฉํ ์ ํ๋ก ์ด์ด์ง๋๋ค.
- TLB(Translation Lookaside Buffer) Flush: ์ฃผ์ ๋ณํ ์ ๋ณด๋ฅผ ๋ด์ TLB ๋ํ ์ค์์นญ ์์ ์ ๋ฌดํจํ๋๊ฑฐ๋ ๊ต์ฒด๋์ด ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจ์จ์ ๋จ์ด๋จ๋ฆฝ๋๋ค.
- ์ํ ๋ณต๊ตฌ ๋น์ฉ: ์บ์๊ฐ ๋ค์ ์ ์๋ฏธํ ํํธ์จ(Hit Rate)์ ๊ธฐ๋กํ ๋๊น์ง ๊ฑธ๋ฆฌ๋ โ์ฝ๋ ์บ์(Cold Cache)โ ๊ตฌ๊ฐ์ ์์คํ ์ ์ฒด์ ๋ณด์ด์ง ์๋ ์ฑ๋ฅ ๋ถ์ฑ๋ฅผ ์ถ์ ํฉ๋๋ค.
๊ณผ๋ํ ์ค๋ ๋ ์์ฑ์ด ์ํํ ์ด์ ย
CPU ์ฝ์ด ์๋ณด๋ค ํจ์ฌ ๋ง์ ์ค๋ ๋๋ฅผ ์์ฑํ๋ฉด ์ปจํ ์คํธ ์ค์์นญ ๋น๋๊ฐ ์ฆ์์ง๊ณ , ์บ์ ์ค์ผ์ด ๋ง์ฑํ๋ฉ๋๋ค. ๊ฒฐ๊ตญ CPU๋ ์ค์ ์ฐ์ฐ๋ณด๋ค โ์บ์๋ฅผ ์ฑ์ฐ๊ณ ๋น์ฐ๋โ ๋ฌด์๋ฏธํ ์์ ์ ๋ ๋ง์ ์ ๋ ฅ์ ์๋ชจํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฅผ โ์ฐ๋ ์ฑ(Thrashing)โ ํ์์ ํ๋์จ์ด์ ๊ด์ ์ผ๋ก ์ดํดํ ์ ์์ต๋๋ค.
๊ฒฐ๊ตญ ์์ง๋์ด๋ ์ํํธ์จ์ด์ ๋ ผ๋ฆฌ์ ๊ฒฉ๋ฆฌ๋ฟ๋ง ์๋๋ผ, ํ๋์จ์ด ์บ์๋ผ๋ ๋ฌผ๋ฆฌ์ ์์์ด ๊ฒช๋ โ๋ง์ฐฐโ์ ์ต์ํํ๋ ๋ฐฉํฅ์ผ๋ก ์ํคํ ์ฒ๋ฅผ ์ค๊ณํด์ผ ํฉ๋๋ค.
Copy-on-Write
์๋ก์ด ํ๋ก์ธ์ค๋ฅผ ๋ง๋๋ fork() ์์คํ
์ฝ์ด ํธ์ถ๋ ๋, ์ด์์ฒด์ ๊ฐ ๋ถ๋ชจ ํ๋ก์ธ์ค์ ๊ฑฐ๋ํ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์ฆ์ ํต์งธ๋ก ๋ณต์ฌํ๋ค๋ฉด ์์คํ
์ ์ด๋ป๊ฒ ๋ ๊น์? ์ ๊ธฐ๊ฐ๋ฐ์ดํธ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ๋ก์ธ์ค๊ฐ ์์ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ ๋๋ง๋ค ๊ทธ๋งํผ์ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ถ๊ฐ๋ก ์ ์ ํ๊ณ ๋ณต์ฌํ๋ ๋ฐ ์๊ฐ์ ๋ณด๋ธ๋ค๋ฉด, ํ๋ ์ปดํจํ
์ ๊ธฐ๋ฏผํจ์ ์ฌ๋ผ์ง ๊ฒ์
๋๋ค. ์ด์์ฒด์ ๋ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Copy-on-Write(์ฐ๊ธฐ ์ ๋ณต์ฌ, ์ดํ COW)๋ผ๋ ๊ณ ๋์ ์ง์ฐ ์ ๋ต์ ์ฌ์ฉํฉ๋๋ค.
fork() ํธ์ถ๊ณผ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ์๋ฆฌํ ๊ด๋ฆฌ
COW์ ํต์ฌ์ โ๊ผญ ํ์ํ ๋๊น์ง ์ผ์ ๋ฏธ๋ฃจ๋ ๊ฒโ์
๋๋ค. fork()๊ฐ ์คํ๋๋ ์๊ฐ ์ด์์ฒด์ ๋ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ณต์ฌํ๋ ๋์ ๋ถ๋ชจ ํ๋ก์ธ์ค์ ํ์ด์ง ํ
์ด๋ธ(Page Table)๋ง์ ๋ณต์ ํฉ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ๋ถ๋ชจ์ ์์ ํ๋ก์ธ์ค๋ ๋์ผํ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ํ์ด์ง๋ฅผ ๋์์ ๊ฐ๋ฆฌํค๊ฒ ๋ฉ๋๋ค. ๊ฒ์ผ๋ก๋ ๋ ๊ฐ์ ๋ ๋ฆฝ๋ ํ๋ก์ธ์ค๊ฐ ์กด์ฌํ์ง๋ง, ์ค์ ํ๋์จ์ด ๋ ๋ฒจ์์๋ ํ๋์ ์์์ ๊ณต์ ํ๊ณ ์๋ ์ ์ ๋๋ค. ์ด ๋๋ถ์ ํ๋ก์ธ์ค ์์ฑ์ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ์ ์๊ด์์ด ์์๊ฐ์ ์๋ฃ๋ฉ๋๋ค.
ํ์ด์ง ํ ์ด๋ธ ๋ณต์ ์ ์ฐ๊ธฐ ์์ ์ ๋ฌผ๋ฆฌ์ ๋ถ๋ฆฌ
๊ณต์ ๋ ํจ์จ์ ์ด์ง๋ง ์ํํฉ๋๋ค. ์์ ํ๋ก์ธ์ค๊ฐ ๊ณต์ ์ค์ธ ๋ฉ๋ชจ๋ฆฌ ๊ฐ์ ์์ ํ๋๋ฐ ๋ถ๋ชจ ํ๋ก์ธ์ค์ ๊ฐ๊น์ง ๋ฐ๋์ด ๋ฒ๋ฆฐ๋ค๋ฉด โ๊ฒฉ๋ฆฌโ๋ผ๋ ํ๋ก์ธ์ค์ ๋์ ์ ๊ฐ ๋ฌด๋์ง๋๋ค. ์ด์์ฒด์ ๋ ์ด๋ฅผ ๋ง๊ธฐ ์ํด ๊ณต์ ๋๋ ๋ชจ๋ ํ์ด์ง๋ฅผ โ์ฝ๊ธฐ ์ ์ฉ(Read-Only)โ์ผ๋ก ์ค์ ํฉ๋๋ค.
์ง์ ํ ๋ง๋ฒ์ ๋๊ตฐ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ค๊ณ ์๋ํ ๋ ์ผ์ด๋ฉ๋๋ค.
- ํ์ด์ง ํดํธ(Page Fault) ๋ฐ์: ํ๋ก์ธ์ค๊ฐ ์ฝ๊ธฐ ์ ์ฉ ํ์ด์ง์ ์ฐ๊ธฐ๋ฅผ ์๋ํ๋ฉด ํ๋์จ์ด๊ฐ ์ด๋ฅผ ๊ฐ์งํ๊ณ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค.
- ์ปค๋ ๊ฐ์ : ์ ์ด๊ถ์ ๋ฐ์ ์ด์์ฒด์ ๋ โ์, ์ด ํ์ด์ง๋ COW ์ค์ ์ด ๋์ด ์๊ตฌ๋โ๋ผ๊ณ ํ๋จํฉ๋๋ค.
- ์ง์ฐ๋ ๋ณต์ฌ: ๊ทธ์ ์ผ ์ด์์ฒด์ ๋ ํด๋น ํ์ด์ง๋ง์ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ์ ์๋ก์ด ์์ญ์ผ๋ก ๋ณต์ฌํฉ๋๋ค.
- ํ์ด์ง ํ ์ด๋ธ ์ ๋ฐ์ดํธ: ์ฐ๊ธฐ๋ฅผ ์๋ํ ํ๋ก์ธ์ค์ ํ์ด์ง ํ ์ด๋ธ์ด ์๋ก ๋ณต์ฌ๋ ๋ฌผ๋ฆฌ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ์ ๋ฐ์ดํธํ๊ณ , ๊ถํ์ โ์ฝ๊ธฐ/์ฐ๊ธฐโ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
Redis๋ ์ด๋ป๊ฒ ์ค๋จ ์์ด ์ค๋ ์ท์ ์ฐ์๊น?
์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ธ Redis๊ฐ ์๋น์ค๋ฅผ ์ค๋จํ์ง ์๊ณ ์์ญ GB์ ๋ฐ์ดํฐ๋ฅผ ๋์คํฌ์ ์ ์ฅ(BGSAVE)ํ ์ ์๋ ๋น๊ฒฐ์ด ๋ฐ๋ก ์ฌ๊ธฐ์ ์์ต๋๋ค.
fork()๋ฅผ ํตํด ์์ ํ๋ก์ธ์ค๋ฅผ ๋ง๋ค๋ฉด COW ๋๋ถ์ ๋ฉ๋ชจ๋ฆฌ ์ถ๊ฐ ์ ์ ์์ด ๊ทธ ์์ ์ ๋ฐ์ดํฐ ์ํ๋ฅผ ๊ณ ์ค๋ํ โ์ค๋ ์ทโ์ผ๋ก ์ฐ์ด๋ผ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main() {
// ์ด๊ธฐ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง ๋ณ์
int data = 100;
pid_t pid;
printf("fork() ์ : data = %d, ์ฃผ์ = %p\n", data, &data);
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork error\n");
return 1;
} else if (pid == 0) {
// [์์ ํ๋ก์ธ์ค]
// ์ด ์์ ๊น์ง๋ COW์ ์ํด ๋ถ๋ชจ์ ๋์ผํ ๋ฌผ๋ฆฌ ํ์ด์ง๋ฅผ ๊ณต์ ํฉ๋๋ค.
printf("[์์] ์ฐ๊ธฐ ์ : data = %d, ์ฃผ์ = %p (๋ถ๋ชจ์ ๊ฐ์ ์ฃผ์ ๋์ผ)\n", data, &data);
// ์์ ํ๋ก์ธ์ค๊ฐ ๊ฐ์ ์์ ํ๋ ์๊ฐ, ํ์ด์ง ๋ณต์ฌ(COW)๊ฐ ๋ฐ์ํฉ๋๋ค.
data = 200;
printf("[์์] ์ฐ๊ธฐ ํ: data = %d, ์ฃผ์ = %p (๊ฐ ๋ณ๊ฒฝ๋จ, ์๋ก์ด ๋ฌผ๋ฆฌ ํ์ด์ง)\n", data, &data);
} else {
// [๋ถ๋ชจ ํ๋ก์ธ์ค]
// ์์์ด ์ข
๋ฃ๋ ๋๊น์ง ๋๊ธฐํ์ฌ ์ถ๋ ฅ์ด ์์ด์ง ์๊ฒ ํฉ๋๋ค.
wait(NULL);
// ๋ถ๋ชจ์ ๋ฐ์ดํฐ๋ ์์์ ์์ ์ ์ํฅ์ ๋ฐ์ง ์์ต๋๋ค (๊ฒฉ๋ฆฌ ๋ณด์ฅ).
printf("[๋ถ๋ชจ] ์์ ์ข
๋ฃ ํ: data = %d, ์ฃผ์ = %p (๊ฐ ์ ์ง๋จ)\n", data, &data);
}
return 0;
}
์ด๋ฌํ COW ๋ฐฉ์์ ํ๋ก์ธ์ค ์์ฑ ๋น์ฉ์ ํ๊ธฐ์ ์ผ๋ก ๋ฎ์ถ์์ ๋ฟ๋ง ์๋๋ผ, ์์คํ ์ ์ฒด์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํจ์จ์ ๊ทน๋ํํ์ต๋๋ค. ์ด์์ฒด์ ๋ ์ด์ฒ๋ผ โํ์ํ ๋๋ง ๋น์ฉ์ ์ง๋ถํ๋โ ๋ฐฉ์์ ํตํด ์ ํ๋ ํ๋์จ์ด ์์ ์์์ ์์ฒ ๊ฐ์ ํ๋ก์ธ์ค๋ฅผ ๋ฅ์ํ๊ฒ ์๋ฆฌํฉ๋๋ค.
M:N Scheduling
์ด์์ฒด์ ๊ฐ ๊ด๋ฆฌํ๋ ์ปค๋ ์ค๋ ๋(Kernel Thread)๋ ๊ฐ๋ ฅํ์ง๋ง ๋น์๋๋ค. ์ค๋ ๋ ํ๋๋ฅผ ์์ฑํ ๋๋ง๋ค ์ฝ 1MB์ ์คํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํ ๋น๋๊ณ , ์ปจํ ์คํธ ์ค์์นญ ๋๋ง๋ค ์ปค๋ ๋ชจ๋ ์ง์ ์ด๋ผ๋ ํตํ๋ฃ๋ฅผ ๋ด์ผ ํฉ๋๋ค. ์๋ง ๊ฐ์ ๋์ ์ ์์ ์ฒ๋ฆฌํด์ผ ํ๋ ํ๋์ ๋ฐฑ์๋ ์์คํ ์์, ์ ์์๋ง๋ค ์ปค๋ ์ค๋ ๋๋ฅผ ํ๋์ฉ ๋ถ์ฌ์ฃผ๋ ๋ฐฉ์์ ์์ ๊ณ ๊ฐ์ ์ง๋ฆ๊ธธ์ ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ๊ฒ์ด ๋ฐ๋ก ์ ์ ๋ ๋ฒจ ์ค๋ ๋์ ์ปค๋ ์ค๋ ๋๋ฅผ ์๋ฆฌํ๊ฒ ๋งคํํ๋ M:N ์ค์ผ์ค๋ง์ ๋๋ค.
์ปค๋ ์ค๋ ๋์ ์ ์ ์ค๋ ๋์ ๋งคํ ์ ๋ต
์ค๋ ๋ ๋ชจ๋ธ์ ํฌ๊ฒ ์ธ ๊ฐ์ง๋ก ์งํํด ์์ต๋๋ค.
- 1:1 ๋ชจ๋ธ: ์ฐ๋ฆฌ๊ฐ ํํ ์๋ Java(์ ํต์ ๋ฒ์ )๋ C++์ ๋ชจ๋ธ์ ๋๋ค. ์ ์ ์ค๋ ๋ ํ๋๊ฐ ์ ํํ ์ปค๋ ์ค๋ ๋ ํ๋์ ๋งคํ๋ฉ๋๋ค. ๊ตฌํ์ด ๋จ์ํ๊ณ ๋ฉํฐ์ฝ์ด๋ฅผ ํ์ฉํ๊ธฐ ์ข์ง๋ง, ์ค๋ ๋ ์์ฑ๊ณผ ์ค์์นญ ๋น์ฉ์ด ๋์ต๋๋ค.
- N:1 ๋ชจ๋ธ: ์ฌ๋ฌ ์ ์ ์ค๋ ๋๊ฐ ๋จ ํ๋์ ์ปค๋ ์ค๋ ๋ ์์์ ๋์๊ฐ๋๋ค. ์ค์์นญ์ ๋งค์ฐ ๋น ๋ฅด์ง๋ง, ๋จ ํ๋์ ์ค๋ ๋๋ง ๋ธ๋กํน ์์คํ ์ฝ์ ํธ์ถํด๋ ๋ชจ๋ ์ค๋ ๋๊ฐ ๋ฉ์ถฐ๋ฒ๋ฆฌ๋ ์น๋ช ์ ์ธ ๋จ์ ์ด ์์ต๋๋ค.
- M:N ๋ชจ๋ธ: ๋ค์์ ์ ์ ์ค๋ ๋๋ฅผ ๊ทธ๋ณด๋ค ์ ์ ์์ ์ปค๋ ์ค๋ ๋์ ๋์ ์ผ๋ก ๋งคํํฉ๋๋ค. Go ์ธ์ด์ Goroutine์ด๋ Java 21์ Virtual Thread๊ฐ ์ฑํํ ๋ฐฉ์์ ๋๋ค.
์ด ๋ชจ๋ธ์์ โ์ ์ ์ค๋ ๋โ๋ ๋ ์ด์ ์ด์์ฒด์ ๊ฐ ๊ด๋ฆฌํ๋ ๋์์ด ์๋๋๋ค. ๋์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ๋ฐํ์์ด ์ค์ผ์ค๋ฌ๋ฅผ ์ง์ ๊ตฌํํ์ฌ, ์ด๋ค ์ ์ ์ค๋ ๋๋ฅผ ์ด๋ค ์ปค๋ ์ค๋ ๋(์์ปค)์ ์ฌ๋ฆด์ง ๊ฒฐ์ ํฉ๋๋ค.
๊ณ ๋ฃจํด๊ณผ ๊ฐ์ ์ค๋ ๋์ ๋ฐํ์ ์ต์ ํ
M:N ๋ชจ๋ธ์ ์ ์๋ โWork Stealingโ ์๊ณ ๋ฆฌ์ฆ์ ์์ต๋๋ค. ํน์ ์ปค๋ ์ค๋ ๋๊ฐ ํ ๋น๋ฐ์ ์ ์ ์ค๋ ๋๋ค์ ๋ชจ๋ ์ฒ๋ฆฌํ์ฌ ํ ์ผ์ด ์์ด์ง๋ฉด, ๋ฐ์๊ฒ ๋์๊ฐ๋ ๋ค๋ฅธ ์ปค๋ ์ค๋ ๋์ ํ์์ ์์ ์ โํ์ณโ ์ต๋๋ค. ์ด๋ฅผ ํตํด ๋ชจ๋ CPU ์ฝ์ด๊ฐ ๋์ง ์๊ณ ์ต๋ํ์ ํจ์จ์ ๋ด๋๋ก ๋ง๋ญ๋๋ค.
์ด๋ฌํ ์ถ์ํ ๋๋ถ์ ๊ฐ๋ฐ์๋ โ์ค๋ ๋ ๊ฐ์โ์ ๋ํ ๊ณตํฌ์์ ๋ฒ์ด๋ ์ ์์ต๋๋ค. ๊ณ ๋ฃจํด(Goroutine)์ ๊ณ ์ ์ KB์ ๋ฉ๋ชจ๋ฆฌ๋ง์ผ๋ก ์์ํ๋ฉฐ, ํ์์ ๋ฐ๋ผ ์คํ ํฌ๊ธฐ๋ฅผ ๋์ ์ผ๋ก ๋๋ฆฝ๋๋ค. Java 21์ ๊ฐ์ ์ค๋ ๋(Virtual Thread) ๋ํ ๊ธฐ์กด์ ๋ธ๋กํน I/O ์ฝ๋๋ฅผ ๊ทธ๋๋ก ์ ์งํ๋ฉด์๋, ๋ด๋ถ์ ์ผ๋ก๋ ์ปค๋ ์ค๋ ๋๋ฅผ ์ ์ ํ์ง ์๊ณ โ์๋ณด(Yield)โํ๋ ๋ฐฉ์์ผ๋ก ์๋ฐฑ๋ง ๊ฐ์ ๋์ ์คํ ํ๋ฆ์ ๊ฐ๋ฅ์ผ ํฉ๋๋ค.
M:N ๋ชจ๋ธ์ ๋ชจ๋ํฐ๋ง ๋น์ฉ
M:N ๋ชจ๋ธ์ ์ฑ๋ฅ ๋ฉด์์ ์๋์ ์ด์ง๋ง, ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ ๋ ์ถ์ ํ๊ธฐ ์ด๋ ต๋ค๋ ํธ๋ ์ด๋์คํ๊ฐ ์์ต๋๋ค. ํน์ ์ ์ ์ค๋ ๋์์ ๋ฐ์ํ ์๋ฌ๊ฐ ์ด๋ค ์ปค๋ ์ค๋ ๋์ ๋ฌธ๋งฅ์์ ํฐ์ง ๊ฒ์ธ์ง ํ์ ํ๊ธฐ ์ํด ๋ ๋ณต์กํ ๋ชจ๋ํฐ๋ง ๋๊ตฌ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// M:N ์ค์ผ์ค๋ง์ ํจ์จ์ฑ์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํด, ๊ธฐ์กด ์ปค๋ ์ค๋ ๋ ๋ฐฉ์์ผ๋ก๋ ๋ถ๊ฐ๋ฅํ ๊ท๋ชจ์ ๋์์ฑ์ ๊ตฌํํฉ๋๋ค.
// (Java 21 ์ด์ ํ์)
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
public class VirtualThreadDemo {
public static void main(String[] args) {
// 10๋ง ๊ฐ์ ๋์ ์์
์ํ. ๊ธฐ์กด ํ๋ซํผ ์ค๋ ๋(1:1 ๋ชจ๋ธ)๋ก๋ ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ(OOM)์ด ๋ฐ์ํ ์ ์๋ ๊ท๋ชจ์
๋๋ค.
int numTasks = 100_000;
System.out.printf("%d๊ฐ์ ๊ฐ์ ์ค๋ ๋ ์์
์์ฑ์ ์์ํฉ๋๋ค...\n", numTasks);
Instant start = Instant.now();
// Executors.newVirtualThreadPerTaskExecutor()๋ ๊ฐ ์์
๋ง๋ค ์๋ก์ด ๊ฐ์ ์ค๋ ๋๋ฅผ ์์ฑํฉ๋๋ค.
// try-with-resources ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๋ฉด ๋ธ๋ก์ ๋น ์ ธ๋๊ฐ ๋ executor.close()๊ฐ ํธ์ถ๋์ด
// ์ ์ถ๋ ๋ชจ๋ ์์
์ด ์๋ฃ๋ ๋๊น์ง ๋ฉ์ธ ์ค๋ ๋๊ฐ ๋๊ธฐํฉ๋๋ค (Structured Concurrency).
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, numTasks).forEach(i -> {
executor.submit(() -> {
try {
// ๊ฐ ์ค๋ ๋๋ I/O ์์
์ ์๋ฎฌ๋ ์ด์
ํ๊ธฐ ์ํด ์ ์ ๋๊ธฐํฉ๋๋ค.
// ๊ฐ์ ์ค๋ ๋๋ ๋ธ๋กํน ์ ์บ๋ฆฌ์ด ์ค๋ ๋(์ปค๋ ์ค๋ ๋)๋ฅผ ์ ์ ํ์ง ์๊ณ '์๋ณด(Yield)'ํฉ๋๋ค.
Thread.sleep(Duration.ofMillis(100));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
});
} // ์ฌ๊ธฐ์ ๋ชจ๋ ๊ฐ์ ์ค๋ ๋์ ์์
์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
Instant end = Instant.now();
System.out.printf("๋ชจ๋ ์์
์ด ์๋ฃ๋์์ต๋๋ค. ์์ ์๊ฐ: %d ms\n", Duration.between(start, end).toMillis());
// ๊ฒฐ๊ณผ์ ์ผ๋ก ์์์ ์ปค๋ ์ค๋ ๋๋ง์ผ๋ก 10๋ง ๊ฐ์ ๋
ผ๋ฆฌ์ ์คํ ํ๋ฆ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํด๋
๋๋ค.
}
}
๊ฒฐ๊ตญ ํ๋์ ์คํ ๋ชจ๋ธ์ โ์ด์์ฒด์ ์ ๊ฒฉ๋ฆฌ(Process)โ ์์์ โ์ธ์ด ๋ฐํ์์ ํจ์จ(M:N Thread)โ์ ์์ ์ฌ๋ฆฌ๋ ๋ฐฉํฅ์ผ๋ก ์์ฑ๋์์ต๋๋ค. ์์ง๋์ด๋ ์ด์ ํ๋์จ์ด์ ์ ์ฝ์ ์ง์ ๊ณ ๋ฏผํ๊ธฐ๋ณด๋ค, ์์ ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ค ์ค์ผ์ค๋ง ๋ชจ๋ธ์ด ์ ํฉํ์ง๋ฅผ ์ ํํ๋ ์๋ชฉ์ ๊ฐ์ถ์ด์ผ ํฉ๋๋ค.
Summary
ํ๋ ์ปดํจํ ์ ํ๋ก์ธ์ค๊ฐ ์ ๊ณตํ๋ โ๊ฒฉ๋ฆฌโ์ ์ค๋ ๋๊ฐ ์ ๊ณตํ๋ โ๊ณต์ โ ์ฌ์ด์ ์ ๊ตํ ์คํ๊ธฐ์ ๋๋ค. ์ด์์ฒด์ ๋ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ๊ณผ PCB๋ฅผ ํตํด ์์คํ ์ ์์ ์ฑ์ ํ๋ณดํ๋ ๋์์, Copy-on-Write์ M:N ์ค์ผ์ค๋ง ๊ฐ์ ์๋ฆฌํ ์ ๋ต์ ํตํด ํ๋์จ์ด ์์์ ๊ทน๋จ์ ์ผ๋ก ์๊ปด ์๋๋ค. ํ์ง๋ง ์ปจํ ์คํธ ์ค์์นญ์ด ๋จ๊ธฐ๋ ์บ์ ์ค์ผ๊ณผ ๋ฉํฐ์ค๋ ๋ฉ์ ์ ๊ธ ๊ฒฝํฉ์ ์ฌ์ ํ ์์ง๋์ด๊ฐ ๊ทน๋ณตํด์ผ ํ ๋ฌผ๋ฆฌ์ ๋ง์ฐฐ๋ก ๋จ์ ์์ต๋๋ค. ๊ฒฐ๊ตญ ํ๋ฅญํ ์ํํธ์จ์ด ์ค๊ณ๋ ์ถ์ํ ์ด๋ฉด์ ํ๋์จ์ด ๋น์ฉ์ ์ ํํ ์ดํดํ๊ณ , ์๋น์ค์ ๋ถํ ํน์ฑ์ ๊ฐ์ฅ ์ ํฉํ ์คํ ๋ชจ๋ธ์ ์ ํํ๋ ์๋ชฉ์์ ๊ฒฐ์ ๋ฉ๋๋ค.





