Post

[OS] Process์™€ Thread

[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)์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ด ๊ณผ์ •์€ ์ƒ๊ฐ๋ณด๋‹ค ํ›จ์”ฌ ๋ฌด๊ฒ๊ณ  ์ •๊ตํ•œ ์•ˆ๋ฌด๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ธํ„ฐ๋ŸฝํŠธ ๋ฐœ์ƒ: ํƒ€์ด๋จธ ์ธํ„ฐ๋ŸฝํŠธ ๋“ฑ์ด ๋ฐœ์ƒํ•˜์—ฌ ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค์˜ ์ œ์–ด๊ถŒ์ด ์ปค๋„๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค.
  2. ์ƒํƒœ ์ €์žฅ: ํ˜„์žฌ CPU์— ๋‚จ์•„์žˆ๋Š” ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’๋“ค(PC, SP ๋“ฑ)์„ ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค์˜ PCB์— ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
  3. ๋‹ค์Œ ํ”„๋กœ์„ธ์Šค ์„ ํƒ: ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๋‹ค์Œ์— ์‹คํ–‰ํ•  ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
  4. ์ƒํƒœ ๋ณต์›: ์„ ํƒ๋œ ํ”„๋กœ์„ธ์Šค์˜ PCB์—์„œ ์ด์ „์— ์ €์žฅํ•ด๋‘์—ˆ๋˜ ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’๋“ค์„ CPU๋กœ ๋‹ค์‹œ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
  5. ์œ ์ € ๋ชจ๋“œ ์ „ํ™˜: ์ปค๋„์€ ์ œ์–ด๊ถŒ์„ ํ”„๋กœ์„ธ์Šค์—๊ฒŒ ๋„˜๊ธฐ๊ณ , ํ”„๋กœ์„ธ์Šค๋Š” ๋งˆ์น˜ ๋ฉˆ์ถ˜ ์  ์—†์—ˆ๋‹ค๋Š” ๋“ฏ์ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ณผ์ •์—์„œ 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)โ€™์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

์ง„์ •ํ•œ ๋งˆ๋ฒ•์€ ๋ˆ„๊ตฐ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์“ฐ๋ ค๊ณ  ์‹œ๋„ํ•  ๋•Œ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.

  1. ํŽ˜์ด์ง€ ํดํŠธ(Page Fault) ๋ฐœ์ƒ: ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฝ๊ธฐ ์ „์šฉ ํŽ˜์ด์ง€์— ์“ฐ๊ธฐ๋ฅผ ์‹œ๋„ํ•˜๋ฉด ํ•˜๋“œ์›จ์–ด๊ฐ€ ์ด๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
  2. ์ปค๋„ ๊ฐœ์ž…: ์ œ์–ด๊ถŒ์„ ๋ฐ›์€ ์šด์˜์ฒด์ œ๋Š” โ€œ์•„, ์ด ํŽ˜์ด์ง€๋Š” COW ์„ค์ •์ด ๋˜์–ด ์žˆ๊ตฌ๋‚˜โ€๋ผ๊ณ  ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.
  3. ์ง€์—ฐ๋œ ๋ณต์‚ฌ: ๊ทธ์ œ์•ผ ์šด์˜์ฒด์ œ๋Š” ํ•ด๋‹น ํŽ˜์ด์ง€๋งŒ์„ ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ์˜ ์ƒˆ๋กœ์šด ์˜์—ญ์œผ๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
  4. ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์—…๋ฐ์ดํŠธ: ์“ฐ๊ธฐ๋ฅผ ์‹œ๋„ํ•œ ํ”„๋กœ์„ธ์Šค์˜ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”์ด ์ƒˆ๋กœ ๋ณต์‚ฌ๋œ ๋ฌผ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ์—…๋ฐ์ดํŠธํ•˜๊ณ , ๊ถŒํ•œ์„ โ€˜์ฝ๊ธฐ/์“ฐ๊ธฐโ€™๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

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:1 ๋ชจ๋ธ: ์šฐ๋ฆฌ๊ฐ€ ํ”ํžˆ ์•„๋Š” Java(์ „ํ†ต์  ๋ฒ„์ „)๋‚˜ C++์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. ์œ ์ € ์Šค๋ ˆ๋“œ ํ•˜๋‚˜๊ฐ€ ์ •ํ™•ํžˆ ์ปค๋„ ์Šค๋ ˆ๋“œ ํ•˜๋‚˜์— ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค. ๊ตฌํ˜„์ด ๋‹จ์ˆœํ•˜๊ณ  ๋ฉ€ํ‹ฐ์ฝ”์–ด๋ฅผ ํ™œ์šฉํ•˜๊ธฐ ์ข‹์ง€๋งŒ, ์Šค๋ ˆ๋“œ ์ƒ์„ฑ๊ณผ ์Šค์œ„์นญ ๋น„์šฉ์ด ๋†’์Šต๋‹ˆ๋‹ค.
  2. N:1 ๋ชจ๋ธ: ์—ฌ๋Ÿฌ ์œ ์ € ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹จ ํ•˜๋‚˜์˜ ์ปค๋„ ์Šค๋ ˆ๋“œ ์œ„์—์„œ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ์Šค์œ„์นญ์€ ๋งค์šฐ ๋น ๋ฅด์ง€๋งŒ, ๋‹จ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ๋ธ”๋กœํ‚น ์‹œ์Šคํ…œ ์ฝœ์„ ํ˜ธ์ถœํ•ด๋„ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฉˆ์ถฐ๋ฒ„๋ฆฌ๋Š” ์น˜๋ช…์ ์ธ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  3. 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 ์Šค์ผ€์ค„๋ง ๊ฐ™์€ ์˜๋ฆฌํ•œ ์ „๋žต์„ ํ†ตํ•ด ํ•˜๋“œ์›จ์–ด ์ž์›์„ ๊ทน๋‹จ์ ์œผ๋กœ ์•„๊ปด ์”๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์ด ๋‚จ๊ธฐ๋Š” ์บ์‹œ ์˜ค์—ผ๊ณผ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์˜ ์ž ๊ธˆ ๊ฒฝํ•ฉ์€ ์—ฌ์ „ํžˆ ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๊ทน๋ณตํ•ด์•ผ ํ•  ๋ฌผ๋ฆฌ์  ๋งˆ์ฐฐ๋กœ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ํ›Œ๋ฅญํ•œ ์†Œํ”„ํŠธ์›จ์–ด ์„ค๊ณ„๋ž€ ์ถ”์ƒํ™” ์ด๋ฉด์˜ ํ•˜๋“œ์›จ์–ด ๋น„์šฉ์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ , ์„œ๋น„์Šค์˜ ๋ถ€ํ•˜ ํŠน์„ฑ์— ๊ฐ€์žฅ ์ ํ•ฉํ•œ ์‹คํ–‰ ๋ชจ๋ธ์„ ์„ ํƒํ•˜๋Š” ์•ˆ๋ชฉ์—์„œ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

References

This post is licensed under CC BY 4.0 by the author.