ํฌ์ŠคํŠธ

CS โ€” process vs thread

CS โ€” process vs thread

๐Ÿ“• 05/07 โ€” ํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ์˜ ์ฐจ์ด์ 

๋ชจ์˜๋ฉด์ ‘ ์ฃผ์ œ: โ€œํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ์˜ ์ฐจ์ด์ ์— ๋Œ€ํ•ด์„œ ์ด์•ผ๊ธฐ ํ•ด์ฃผ์„ธ์š”โ€ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ โ†’ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ โ†’ IPC vs ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ โ†’ ๋™๊ธฐํ™” โ†’ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค/๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์„ ํƒ โ†’ ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ/๋ Œ๋” ์Šค๋ ˆ๋“œ๊นŒ์ง€


ํ•™์Šต ์˜์—ญ ์ „ํ™˜์  โ€” ์ž๋ฃŒ๊ตฌ์กฐยทSTL์—์„œ OSยท๋™์‹œ์„ฑ์œผ๋กœ

13~18๋ฒˆ์—์„œ STL ์ปจํ…Œ์ด๋„ˆ์™€ ์•Œ๊ณ ๋ฆฌ์ฆ˜(vector/list, find/binary_search, list::sort ๋“ฑ)์„ ์ •๋ฆฌํ–ˆ๋‹ค๋ฉด, 19๋ฒˆ๋ถ€ํ„ฐ๋Š” ์šด์˜์ฒด์ œ(OS) ์˜์—ญ์œผ๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ โ€œ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฐฐ์น˜ํ•˜๋‚˜โ€์˜ ๋ฌธ์ œ์˜€๋‹ค๋ฉด, ๋™์‹œ์„ฑ์€ โ€œ์—ฌ๋Ÿฌ ์‹คํ–‰ ํ๋ฆ„์ด ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ณต์œ ํ•˜๊ณ  ์ถฉ๋Œ์„ ํ”ผํ•˜๋‚˜โ€œ์˜ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

1
2
3
4
5
13~18๋ฒˆ  STL ์ปจํ…Œ์ด๋„ˆยท์•Œ๊ณ ๋ฆฌ์ฆ˜                โ€” ์ž๋ฃŒ๊ตฌ์กฐ ๋„๋ฉ”์ธ
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
19๋ฒˆ    ํ”„๋กœ์„ธ์Šค vs ์Šค๋ ˆ๋“œ โ˜…                  โ€” OS ๋„๋ฉ”์ธ ์ง„์ž…
์ดํ›„    ๋ฎคํ…์Šคยท์„ธ๋งˆํฌ์–ดยท๋ฐ๋“œ๋ฝ / ์Šค์ผ€์ค„๋Ÿฌ     โ€” ๋™์‹œ์„ฑ ๊นŠ์ด
        ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌยทํŽ˜์ด์ง•ยท์Šคํƒ vs ํž™ (์žฌ๋ฐฉ๋ฌธ) โ€” ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ

์ด ์ฃผ์ œ๋Š” 11๋ฒˆ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ์˜ shared_ptr ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ(์ œ์–ด ๋ธ”๋ก atomic ์นด์šดํ„ฐ), 16๋ฒˆ STL ์ปจํ…Œ์ด๋„ˆ์˜ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ ์ปจ๋ฒค์…˜(๊ฐœ๋ณ„ ์ปจํ…Œ์ด๋„ˆ๋Š” thread-safeํ•˜์ง€ ์•Š์Œ)๊ณผ๋„ ์ง์ ‘ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•œ ๋‹จ๊ณ„ ๋” ๋“ค์–ด๊ฐ€๋ฉด mutexยทlock_guardยทscoped_lock(GRAPH_REPORT์˜ Community 18ยท23) ๊ฐ™์€ RAII ๋ฝ ํŒจํ„ด์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์ด์–ด์ง‘๋‹ˆ๋‹ค โ€” ์ด๊ฒƒ๋„ 9๋ฒˆ RAII์˜ ๋™์‹œ์„ฑ ๋ฒ„์ „์ž…๋‹ˆ๋‹ค.


๋ชจ์˜๋ฉด์ ‘ ๋‹ต๋ณ€

ํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ๋Š” ๋ชจ๋‘ ์‹คํ–‰ ๋‹จ์œ„์ง€๋งŒ, ์ž์› ์†Œ์œ  ๋‹จ์œ„์ธ์ง€ ์‹คํ–‰ ํ๋ฆ„ ๋‹จ์œ„์ธ์ง€์—์„œ ๊ฒฐ์ •์ ์œผ๋กœ ๊ฐˆ๋ฆฝ๋‹ˆ๋‹ค.

ํ”„๋กœ์„ธ์Šค๋Š” ์šด์˜์ฒด์ œ๋กœ๋ถ€ํ„ฐ ์ž์›์„ ํ• ๋‹น๋ฐ›๋Š” ์ž‘์—…์˜ ๋‹จ์œ„์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„(์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™ยท์Šคํƒ), ํŒŒ์ผ ํ•ธ๋“ค, ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๋…๋ฆฝ์ ์œผ๋กœ ์†Œ์œ ํ•ฉ๋‹ˆ๋‹ค. ํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ณ , ํ†ต์‹ ํ•˜๋ ค๋ฉด IPC(ํŒŒ์ดํ”„ยท๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌยท์†Œ์ผ“ ๋“ฑ) ๊ฐ™์€ ๋ช…์‹œ์  ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์Šค๋ ˆ๋“œ๋Š” ํ”„๋กœ์„ธ์Šค ์•ˆ์—์„œ ์‹ค์ œ๋กœ CPU๋ฅผ ์ ์œ ํ•ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ๋ฆ„์˜ ๋‹จ์œ„์ž…๋‹ˆ๋‹ค. ํ•œ ํ”„๋กœ์„ธ์Šค ์•ˆ์˜ ์Šค๋ ˆ๋“œ๋“ค์€ ์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™์„ ๊ณต์œ ํ•˜๊ณ  ์Šคํƒ๊ณผ ๋ ˆ์ง€์Šคํ„ฐ, PC๋งŒ ๊ฐ์ž ๊ฐ–์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์Šค๋ ˆ๋“œ๋ผ๋ฆฌ๋Š” ์ „์—ญ ๋ณ€์ˆ˜๋‚˜ ํž™์— ํ• ๋‹น๋œ ๊ฐ์ฒด๋กœ ๋ณ„๋„ ๋น„์šฉ ์—†์ด ํ†ต์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ์—์„œ ์ฐจ์ด๊ฐ€ ํฝ๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค ์ „ํ™˜์€ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๋ฐ”๊ฟ”์•ผ ํ•ด์„œ TLB(Translation Lookaside Buffer)๋ฅผ ๋น„์šฐ๊ณ (flush), ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šค ๋ ˆ์ง€์Šคํ„ฐ(CR3)๋ฅผ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์งํ›„์—” L1ยทL2 ์บ์‹œ๋„ ์ƒˆ ํ”„๋กœ์„ธ์Šค ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์–ด ๋ฏธ์Šค๊ฐ€ ์ž‡๋”ฐ๋ผ ๋ฐœ์ƒํ•˜๋Š” โ€œcache coldโ€(์บ์‹œ ์ฝœ๋“œ) ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ ์ „ํ™˜์€ ๊ฐ™์€ ์ฃผ์†Œ ๊ณต๊ฐ„ ์•ˆ์—์„œ ์ผ์–ด๋‚˜๋ฏ€๋กœ TLBยทํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”์„ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ๋ ˆ์ง€์Šคํ„ฐ๋งŒ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์Šค๋ ˆ๋“œ ์ „ํ™˜์ด ํ”„๋กœ์„ธ์Šค ์ „ํ™˜๋ณด๋‹ค 5~10๋ฐฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ณต์œ ์˜ ๋Œ€๊ฐ€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋™์‹œ์— ๊ฑด๋“œ๋ฆฌ๋ฉด race condition์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. count++ ํ•œ ์ค„๋„ ์‚ฌ์‹ค์€ loadยทaddยทstore ์„ธ ๋‹จ๊ณ„๋ผ ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ์ธํ„ฐ๋ฆฌ๋น™๋˜๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๊นจ์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ mutex, atomic, condition variable ๊ฐ™์€ ๋™๊ธฐํ™” ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•˜๊ณ , ์ž˜๋ชป ์“ฐ๋ฉด deadlockยทlivelockยทpriority inversion ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ฒฉ๋ฆฌ๋ผ ์žˆ์–ด์„œ ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ์›์ฒœ์ ์œผ๋กœ ์ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‘˜์€ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ๊ด€๊ณ„์ž…๋‹ˆ๋‹ค. ๊ฒฉ๋ฆฌยท์•ˆ์ •์„ฑ์ด ์ค‘์š”ํ•˜๋ฉด ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค(Chrome ํƒญ ๋ถ„๋ฆฌยทPostgres ์›Œ์ปค), ๋น ๋ฅธ ํ†ต์‹ ยท๋‚ฎ์€ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ค‘์š”ํ•˜๋ฉด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ(๊ฒŒ์ž„ ์—”์ง„ยท์›น ์„œ๋ฒ„ ์›Œ์ปค). ๊ฒŒ์ž„ ์—”์ง„์€ ๋งค ํ”„๋ ˆ์ž„ 60fps๋ฅผ ๋งž์ถฐ์•ผ ํ•˜๋‹ˆ ํ†ต์‹  ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ํฐ IPC๋Š” ๋ถ€๋‹ด์ด๊ณ , ๊ทธ๋ž˜์„œ ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ์™€ ๋ Œ๋” ์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ์•ˆ์—์„œ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ + ๋™๊ธฐํ™”๋กœ ์šด์šฉํ•ฉ๋‹ˆ๋‹ค. ์–ธ๋ฆฌ์–ผ ์—”์ง„๋„ FRunnable, AsyncTask, ParallelFor ๊ฐ™์€ ์ถ”์ƒํ™”๋ฅผ ํ†ตํ•ด ์ด ๋ชจ๋ธ์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.


ํ•ต์‹ฌ ๊ฐœ๋…

๋ถ„๋ฅ˜ํ‚ค์›Œ๋“œํ•œ ์ค„ ์ •์˜
์ •์˜ํ”„๋กœ์„ธ์Šค (Process)์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ๊ทธ๋žจ. ์ž์› ์†Œ์œ  ๋‹จ์œ„ (๋ฉ”๋ชจ๋ฆฌยทํ•ธ๋“ค ๋…๋ฆฝ)
ย ์Šค๋ ˆ๋“œ (Thread)ํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€ ์‹คํ–‰ ํ๋ฆ„ ๋‹จ์œ„. ์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™ ๊ณต์œ 
๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ์ฝ”๋“œ ์˜์—ญ (Text)์‹คํ–‰ ๋ช…๋ น์–ด. read-only, ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ณต์œ 
ย ๋ฐ์ดํ„ฐ ์˜์—ญ (Data/BSS)์ „์—ญยทstatic ๋ณ€์ˆ˜. ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ณต์œ 
ย ํž™ (Heap)new/malloc๋กœ ๋™์  ํ• ๋‹น. ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ณต์œ 
ย ์Šคํƒ (Stack)์ง€์—ญ ๋ณ€์ˆ˜ยทํ•จ์ˆ˜ ํ˜ธ์ถœ. ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ๋…๋ฆฝ
์ œ์–ด ๋ธ”๋กPCB (Process Control Block)OS๊ฐ€ ํ”„๋กœ์„ธ์Šค ์ •๋ณด ๊ด€๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ์ฒด (PIDยท๋ฉ”๋ชจ๋ฆฌ๋งตยทํ•ธ๋“ค ๋“ฑ)
ย TCB (Thread Control Block)์Šค๋ ˆ๋“œ ์ •๋ณด (TIDยท๋ ˆ์ง€์Šคํ„ฐยท์Šคํƒ ํฌ์ธํ„ฐยทPC)
์ปจํ…์ŠคํŠธ ์Šค์œ„์นญTLB (Translation Lookaside Buffer)๊ฐ€์ƒโ†’๋ฌผ๋ฆฌ ์ฃผ์†Œ ์บ์‹œ. ํ”„๋กœ์„ธ์Šค ์ „ํ™˜ ์‹œ flush
ย CR3 / ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šคํ”„๋กœ์„ธ์Šค ์ „ํ™˜ ์‹œ ๊ต์ฒด โ€” ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ๊ฐˆ์•„ํƒ
ย PC (Program Counter)๋‹ค์Œ์— ์‹คํ–‰ํ•  ๋ช…๋ น์–ด์˜ ์ฃผ์†Œ. ์Šค๋ ˆ๋“œ ์ „ํ™˜ ์‹œ ๊ต์ฒด โ€” โ€œ์–ด๋””๊นŒ์ง€ ์‹คํ–‰ํ–ˆ๋Š”์ง€โ€
ย SP (Stack Pointer)ํ˜„์žฌ ์Šคํƒ์˜ ์ตœ์ƒ๋‹จ ์ฃผ์†Œ. ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ์ž๊ธฐ ์Šคํƒ์„ ๊ฐ€๋ฆฌํ‚ด
ย ๋ฒ”์šฉ ๋ ˆ์ง€์Šคํ„ฐ (General Purpose Register)x86_64 ๊ธฐ์ค€ raxยทrbxยทrcxยทrdxยทrsiยทrdiยทr8~r15 ๋“ฑ. ์—ฐ์‚ฐ ์ค‘์ธ ์ž„์‹œ ๊ฐ’ยทํ•จ์ˆ˜ ์ธ์žยท๋ฆฌํ„ด๊ฐ’ ์ €์žฅ
ย ๋ ˆ์ง€์Šคํ„ฐ ์ปจํ…์ŠคํŠธ์œ„ ์…‹(PCยทSPยท๋ฒ”์šฉ)์„ ๋ฌถ์–ด ๋ถ€๋ฅด๋Š” ๋ง. TCB์— ์ €์žฅ๋๋‹ค๊ฐ€ ๋ณต์› โ€” ์Šค๋ ˆ๋“œ ์ „ํ™˜์˜ ๋ณธ์ฒด
ํ†ต์‹ IPC (Inter-Process Communication)ํ”„๋กœ์„ธ์Šค ๊ฐ„ ํ†ต์‹ . ํŒŒ์ดํ”„ยท๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌยท๋ฉ”์‹œ์ง€ ํยท์†Œ์ผ“
ย ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ / ์ „์—ญ ๋ณ€์ˆ˜์Šค๋ ˆ๋“œ ๊ฐ„ ํ†ต์‹ ์˜ ๊ธฐ๋ณธ โ€” ๊ฐ™์€ ์ฃผ์†Œ ๊ณต๊ฐ„์ด๋ผ ๊ทธ๋ƒฅ ์ ‘๊ทผ
๋™๊ธฐํ™”race condition์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ์— ๋™์‹œ ์ ‘๊ทผํ•ด ๊ฒฐ๊ณผ๊ฐ€ ๋น„๊ฒฐ์ •์ 
ย ์ž„๊ณ„ ๊ตฌ์—ญ (Critical Section)ํ•œ ๋ฒˆ์— ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ฝ”๋“œ ๊ตฌ๊ฐ„
ย mutex (mutual exclusion)์ƒํ˜ธ ๋ฐฐ์ œ ๋ฝ. ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ์ž์› ์ ์œ 
ย deadlock๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ์„œ๋กœ์˜ ๋ฝ์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ์˜์›ํžˆ ๋ฉˆ์ถค (4๊ฐ€์ง€ ์กฐ๊ฑด)
ย atomicCPU ๋ช…๋ น์–ด๋กœ ๋ณด์žฅ๋˜๋Š” ์›์ž์  ์—ฐ์‚ฐ (lock-free)
๋ชจ๋ธ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ์‚ฌ์šฉ์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ด€๋ฆฌ. ๋น ๋ฅด์ง€๋งŒ ์‹œ์Šคํ…œ ์ฝœ ์ฐจ๋‹จ์— ์ทจ์•ฝ
ย ์ปค๋„ ์Šค๋ ˆ๋“œOS ์ง์ ‘ ๊ด€๋ฆฌ. ์‹œ์Šคํ…œ ์ฝœ ์ž์œ ๋กœ์›€
ย 1:1 ๋ชจ๋ธ์œ ์ € 1 โ†” ์ปค๋„ 1. WindowsยทLinux pthread
ย N:1 ๋ชจ๋ธ์œ ์ € N โ†’ ์ปค๋„ 1. ๊ฐ€๋ฒผ์šฐ๋‚˜ ํ•œ ์‹œ์Šคํ…œ ์ฝœ์— ์ „๋ถ€ ์ฐจ๋‹จ
ย M:N ๋ชจ๋ธ์œ ์ € M โ†’ ์ปค๋„ N. Go ๊ณ ๋ฃจํ‹ด ๋“ฑ
C++ APIstd::threadC++11 ํ‘œ์ค€ ์Šค๋ ˆ๋“œ. 1:1 ๋ชจ๋ธ (OS ์Šค๋ ˆ๋“œ ๋ž˜ํ•‘)
ย std::mutex์ƒํ˜ธ ๋ฐฐ์ œ ๋ฝ. ๋ณต์‚ฌยท์ด๋™ ๋ถˆ๊ฐ€ (Community 23)
ย std::lock_guardRAII ๋ฝ. ์ƒ์„ฑ ์‹œ lock, ์†Œ๋ฉธ ์‹œ unlock
ย std::scoped_lock (C++17)์—ฌ๋Ÿฌ mutex ๋™์‹œ ๋ฝ. ๋ฐ๋“œ๋ฝ ํšŒํ”ผ
ย std::async/std::future๋น„๋™๊ธฐ ์ž‘์—… ์‹คํ–‰ + ๊ฒฐ๊ณผ ๊ธฐ๋‹ค๋ฆผ
ย std::atomic<T>์›์ž์  ๋ณ€์ˆ˜. ๋ฝ ์—†์ด ์•ˆ์ „ํ•œ read-modify-write
์–ธ๋ฆฌ์–ผ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ (Game Thread)๋ฉ”์ธ ์Šค๋ ˆ๋“œ. AActorยทTickยทUI ์ฒ˜๋ฆฌ
ย ๋ Œ๋” ์Šค๋ ˆ๋“œ (Render Thread)๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ์˜ ๋ช…๋ น์„ ๋ฐ›์•„ GPU ๋ช…๋ น์–ด ์ƒ์„ฑ
ย FRunnable / FRunnableThread์–ธ๋ฆฌ์–ผ ์›Œ์ปค ์Šค๋ ˆ๋“œ ์ถ”์ƒํ™”
ย AsyncTask / ParallelFor์งง์€ ์ž‘์—… ํ’€ ๋””์ŠคํŒจ์น˜ / ๋ณ‘๋ ฌ ๋ฃจํ”„
ย FCriticalSection / FScopeLockmutex / RAII ๋ฝ (Community 7)
์‚ฌ๋ก€Chrome ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šคํƒญ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค โ€” ๊ฒฉ๋ฆฌยท๋ณด์•ˆ
ย ๊ฒŒ์ž„ ์—”์ง„ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค์˜ ๊ฒŒ์ž„/๋ Œ๋” ์Šค๋ ˆ๋“œ โ€” 60fps ์œ„ํ•ด IPC ํšŒํ”ผ

๋ชฉ์ฐจ

  1. ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ
  2. ํ•œ ์ค„ ์ •์˜ โ€” ํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ
  3. ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋น„๊ต โ€” ์ฝ”๋“œ/๋ฐ์ดํ„ฐ/ํž™/์Šคํƒ๊ณผ PCB/TCB
  4. ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ โ€” ์™œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋น ๋ฅธ๊ฐ€
  5. ํ†ต์‹  ๋ฐฉ์‹ โ€” IPC vs ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ
  6. ๋™๊ธฐํ™” ๋ฌธ์ œ โ€” race condition / mutex / deadlock
  7. ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค vs ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ โ€” ์–ธ์ œ ๋ฌด์—‡์„ ์“ฐ๋‚˜
  8. ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ vs ์ปค๋„ ์Šค๋ ˆ๋“œ โ€” 1:1 / N:1 / M:N ๋ชจ๋ธ
  9. C++ ์ฝ”๋“œ ์˜ˆ์‹œ โ€” std::thread / mutex / async / atomic
  10. ์–ธ๋ฆฌ์–ผ์—์„œ์˜ ์Šค๋ ˆ๋“œ โ€” ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ / ๋ Œ๋” ์Šค๋ ˆ๋“œ / FRunnable
  11. ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์˜ˆ์ƒ ๊ฒฝ๋กœ

1. ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ

30์ดˆ ๋‹ต๋ณ€

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ํ”„๋กœ์„ธ์Šค = ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ๊ทธ๋žจ. ์ž์› ์†Œ์œ  ๋‹จ์œ„.
           ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„(์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™ยท์Šคํƒ)ยทํ•ธ๋“คยท๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐ€์ง.
           ํ†ต์‹ ์€ IPC (ํŒŒ์ดํ”„ยท๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌยท์†Œ์ผ“ ๋“ฑ ๋ช…์‹œ์  ๋ฉ”์ปค๋‹ˆ์ฆ˜).

์Šค๋ ˆ๋“œ   = ํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€์˜ ์‹คํ–‰ ํ๋ฆ„. CPU ์ ์œ  ๋‹จ์œ„.
           ์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™์€ ๊ณต์œ , ์Šคํƒยท๋ ˆ์ง€์Šคํ„ฐยทPC๋งŒ ๊ฐ์ž.
           ํ†ต์‹ ์€ ์ „์—ญ ๋ณ€์ˆ˜ยทํž™ ๊ฐ์ฒด๋กœ ์ฆ‰์‹œ ๊ฐ€๋Šฅ (๊ทธ๋Ÿฌ๋‚˜ ๋™๊ธฐํ™” ํ•„์š”).

์ฐจ์ด 3๊ฐ€์ง€:
  โ‘  ์ž์› ์†Œ์œ  โ€” ํ”„๋กœ์„ธ์Šค๋Š” ๋…๋ฆฝ, ์Šค๋ ˆ๋“œ๋Š” ๊ณต์œ 
  โ‘ก ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ โ€” ์Šค๋ ˆ๋“œ๊ฐ€ 5~10๋ฐฐ ๋น ๋ฆ„ (TLB flush ์—†์Œ)
  โ‘ข ํ†ต์‹  โ€” IPC vs ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ (์†๋„์™€ ์•ˆ์ „์„ฑ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„)

์„ ํƒ ๊ธฐ์ค€:
  ๊ฒฉ๋ฆฌยท์•ˆ์ •์„ฑ โ†’ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค (Chrome ํƒญ, Postgres ์›Œ์ปค)
  ์†๋„ยทํ†ต์‹    โ†’ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ (๊ฒŒ์ž„ ์—”์ง„, ์›น ์„œ๋ฒ„ ์›Œ์ปค)

๊ฒŒ์ž„ ์—”์ง„: ๋งค ํ”„๋ ˆ์ž„ 60fps โ†’ IPC ๋ถ€๋‹ด โ†’ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ (๊ฒŒ์ž„/๋ Œ๋” ์Šค๋ ˆ๋“œ)

๊ผฌ๋ฆฌ์งˆ๋ฌธ ์—ฐ๊ฒฐ ๋งต

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ํ”„๋กœ์„ธ์Šค vs ์Šค๋ ˆ๋“œ
โ”œโ”€โ”€ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ โ†’ ์ฝ”๋“œ/๋ฐ์ดํ„ฐ/ํž™์€ ๊ณต์œ , ์Šคํƒ์€ ๋…๋ฆฝ
โ”‚   โ””โ”€โ”€ PCB vs TCB (TCB๊ฐ€ ํ›จ์”ฌ ๊ฐ€๋ฒผ์›€)
โ”œโ”€โ”€ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ โ†’ ์™œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋น ๋ฅธ๊ฐ€?
โ”‚   โ”œโ”€โ”€ TLB flush ํšŒํ”ผ
โ”‚   โ””โ”€โ”€ ์บ์‹œ locality ์œ ์ง€
โ”œโ”€โ”€ ํ†ต์‹  โ†’ IPC vs ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ
โ”‚   โ”œโ”€โ”€ ํŒŒ์ดํ”„ยท๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌยท์†Œ์ผ“ยท๋ฉ”์‹œ์ง€ ํ
โ”‚   โ””โ”€โ”€ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ = ์œ„ํ—˜ โ†’ mutex ํ•„์š”
โ”œโ”€โ”€ ๋™๊ธฐํ™” โ†’ race condition / mutex / deadlock
โ”‚   โ”œโ”€โ”€ lock_guard / scoped_lock (RAII)  โ† 9๋ฒˆ RAII ํšŒ๊ท€
โ”‚   โ”œโ”€โ”€ atomic โ€” lock-free (shared_ptr ์ œ์–ด ๋ธ”๋ก)  โ† 11๋ฒˆ ํšŒ๊ท€
โ”‚   โ””โ”€โ”€ deadlock 4์กฐ๊ฑด + ํšŒํ”ผ ํŒจํ„ด
โ”œโ”€โ”€ ๋ชจ๋ธ โ†’ 1:1 / N:1 / M:N
โ”‚   โ”œโ”€โ”€ std::thread (1:1)
โ”‚   โ””โ”€โ”€ Go goroutine (M:N)
โ”œโ”€โ”€ ์‚ฌ๋ก€
โ”‚   โ”œโ”€โ”€ Chrome (๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค โ€” ๋ณด์•ˆยท๊ฒฉ๋ฆฌ)
โ”‚   โ”œโ”€โ”€ Postgres (๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค โ€” ์•ˆ์ •์„ฑ)
โ”‚   โ”œโ”€โ”€ Apache vs Nginx (์Šค๋ ˆ๋“œ vs ์ด๋ฒคํŠธ)
โ”‚   โ””โ”€โ”€ ๊ฒŒ์ž„ ์—”์ง„ (๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ โ€” 60fps)
โ””โ”€โ”€ ์–ธ๋ฆฌ์–ผ โ†’ ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ / ๋ Œ๋” ์Šค๋ ˆ๋“œ / FRunnable / AsyncTask / FScopeLock

2. ํ•œ ์ค„ ์ •์˜ โ€” ํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

ํ”„๋กœ์„ธ์Šค๋Š” ์ž์›์„ ์†Œ์œ ํ•˜๋Š” ๋‹จ์œ„๊ณ , ์Šค๋ ˆ๋“œ๋Š” ๊ทธ ์ž์› ์œ„์—์„œ ์‹คํ–‰๋˜๋Š” ํ๋ฆ„์ž…๋‹ˆ๋‹ค.

ํ”„๋กœ์„ธ์Šค (Process)

โ€œ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ๊ทธ๋žจ์˜ ์ธ์Šคํ„ด์Šค.โ€ ๋””์Šคํฌ์— ์žˆ๋Š” ์‹คํ–‰ ํŒŒ์ผ์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋˜์–ด OS๋กœ๋ถ€ํ„ฐ ์ž์›์„ ํ• ๋‹น๋ฐ›์€ ์ƒํƒœ.

1
2
3
4
5
6
7
8
ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ฐ€์ง„ ๊ฒƒ:
  โ”œโ”€ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ (์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™ยท์Šคํƒ)
  โ”œโ”€ ํŒŒ์ผ ํ•ธ๋“ค / ์†Œ์ผ“ ๋””์Šคํฌ๋ฆฝํ„ฐ
  โ”œโ”€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜
  โ”œโ”€ PID (ํ”„๋กœ์„ธ์Šค ์‹๋ณ„์ž)
  โ”œโ”€ ์ž์‹ ํ”„๋กœ์„ธ์Šค ์ •๋ณด, ๋ถ€๋ชจ PID
  โ”œโ”€ CPU ๋ ˆ์ง€์Šคํ„ฐ ์ƒํƒœ (์Šค๋ ˆ๋“œ 1๊ฐœ ์ด์ƒ)
  โ””โ”€ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” (๊ฐ€์ƒโ†’๋ฌผ๋ฆฌ ์ฃผ์†Œ ๋งคํ•‘)

โ†’ ํ”„๋กœ์„ธ์Šค๋Š” ๊ฒฉ๋ฆฌ(isolation)๊ฐ€ ๊ธฐ๋ณธ์ž…๋‹ˆ๋‹ค. A ํ”„๋กœ์„ธ์Šค๊ฐ€ B ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง์ ‘ ์ฝ์œผ๋ ค ํ•˜๋ฉด OS๊ฐ€ segfault๋กœ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค.

์Šค๋ ˆ๋“œ (Thread)

โ€œํ”„๋กœ์„ธ์Šค ๋‚ด๋ถ€์—์„œ CPU๋ฅผ ์ ์œ ํ•ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ๋ฆ„.โ€ ํ•œ ํ”„๋กœ์„ธ์Šค ์•ˆ์— ์—ฌ๋Ÿฌ ๊ฐœ ์กด์žฌํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฐ๊ฐ์ด ๋…๋ฆฝ์ ์œผ๋กœ ์Šค์ผ€์ค„๋ง๋ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ€์ง„ ๊ฒƒ (์ž๊ธฐ๋งŒ์˜):
  โ”œโ”€ ์Šคํƒ
  โ”œโ”€ ๋ ˆ์ง€์Šคํ„ฐ ์ปจํ…์ŠคํŠธ (PC, SP, ๋ฒ”์šฉ ๋ ˆ์ง€์Šคํ„ฐ)
  โ”œโ”€ TID (์Šค๋ ˆ๋“œ ์‹๋ณ„์ž)
  โ”œโ”€ ์‹œ๊ทธ๋„ ๋งˆ์Šคํฌ
  โ””โ”€ TLS (Thread Local Storage)

์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ (ํ”„๋กœ์„ธ์Šค ์•ˆ์˜ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์™€):
  โ”œโ”€ ์ฝ”๋“œ ์˜์—ญ (Text)
  โ”œโ”€ ์ „์—ญยทstatic ๋ฐ์ดํ„ฐ (Data/BSS)
  โ”œโ”€ ํž™
  โ”œโ”€ ํŒŒ์ผ ํ•ธ๋“ค
  โ””โ”€ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ „์ฒด

โ†’ โ€œ์Šค๋ ˆ๋“œ = light-weight process(LWP)โ€๋ผ๊ณ ๋„ ๋ถ€๋ฅด๋Š” ์ด์œ . ์ƒˆ ํ”„๋กœ์„ธ์Šค ๋งŒ๋“œ๋Š” ๊ฒƒ๋ณด๋‹ค ์ƒˆ ์Šค๋ ˆ๋“œ ๋งŒ๋“œ๋Š” ๊ฒŒ ํ›จ์”ฌ ๊ฐ€๋ณ์Šต๋‹ˆ๋‹ค.

๋น„์œ ๋กœ

1
2
3
4
5
6
7
8
9
ํ”„๋กœ์„ธ์Šค = ํ•œ ์ฑ„์˜ ์ง‘
  โ”œโ”€ ์ž๊ธฐ ๋งˆ๋‹น, ์ž๊ธฐ ๋ถ€์—Œ, ์ž๊ธฐ ์š•์‹ค (๋…๋ฆฝ ์ž์›)
  โ””โ”€ ๋‹ค๋ฅธ ์ง‘๊ณผ ํ†ต์‹ ํ•˜๋ ค๋ฉด ์šฐํŽธยท์ „ํ™” (IPC)

์Šค๋ ˆ๋“œ = ๊ฐ™์€ ์ง‘ ์•ˆ์— ์‚ฌ๋Š” ๊ฐ€์กฑ ๊ตฌ์„ฑ์›
  โ”œโ”€ ๋ถ€์—Œยท๊ฑฐ์‹คยทํ™”์žฅ์‹ค์€ ๊ณต์œ  (์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™)
  โ””โ”€ ์ž๊ธฐ ์นจ๋Œ€ยท์˜ท์žฅ์€ ๋…๋ฆฝ (์Šคํƒยท๋ ˆ์ง€์Šคํ„ฐ)
  โ””โ”€ ํ•œ ํ™”์žฅ์‹ค์— ์—ฌ๋Ÿฌ ๋ช…์ด ๋™์‹œ์— ๋“ค์–ด๊ฐ€๋ฉด ์ถฉ๋Œ (race condition)
       โ†’ ๋ฌธ์— ์ž ๊ธˆ ํ•„์š” (mutex)

3. ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ ๋น„๊ต โ€” ์ฝ”๋“œ/๋ฐ์ดํ„ฐ/ํž™/์Šคํƒ๊ณผ PCB/TCB

๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ 4๊ตฌ์—ญ ๋ณต๊ธฐ (01_runtime, 03_new_vs_malloc ํšŒ๊ท€)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
๋†’์€ ์ฃผ์†Œ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   ์Šคํƒ (Stack)   โ”‚  โ† ์ง€์—ญ ๋ณ€์ˆ˜, ํ•จ์ˆ˜ ํ˜ธ์ถœ ํ”„๋ ˆ์ž„. ์Šค๋ ˆ๋“œ๋งˆ๋‹ค ๋…๋ฆฝ.
โ”‚       โ†“         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚                 โ”‚
โ”‚   ํž™ (Heap)     โ”‚  โ† new/malloc. ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ณต์œ . โ˜… ๋™๊ธฐํ™” ํ•„์š”
โ”‚       โ†‘         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Data / BSS      โ”‚  โ† ์ „์—ญยทstatic ๋ณ€์ˆ˜. ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ณต์œ . โ˜… ๋™๊ธฐํ™” ํ•„์š”
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Code (Text)     โ”‚  โ† ์‹คํ–‰ ๋ช…๋ น์–ด. read-only. ๊ณต์œ  (์ž์—ฐ์Šค๋Ÿฌ์›€)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
๋‚ฎ์€ ์ฃผ์†Œ

๋‹จ์ผ ์Šค๋ ˆ๋“œ vs ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ

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
๋‹จ์ผ ์Šค๋ ˆ๋“œ ํ”„๋กœ์„ธ์Šค
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Stack (1๊ฐœ)         โ”‚
โ”‚      โ†“              โ”‚
โ”‚                     โ”‚
โ”‚      โ†‘              โ”‚
โ”‚ Heap                โ”‚
โ”‚ Data                โ”‚
โ”‚ Code                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ”„๋กœ์„ธ์Šค (์Šค๋ ˆ๋“œ 3๊ฐœ)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Stack 1 โ”‚ Stack 2   โ”‚  โ† ๊ฐ ์Šค๋ ˆ๋“œ์˜ ๋…๋ฆฝ ์Šคํƒ
โ”‚   โ†“     โ”‚   โ†“       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Stack 3 โ”‚           โ”‚
โ”‚   โ†“     โ”‚           โ”‚
โ”‚         โ”‚           โ”‚
โ”‚ โ˜… ๊ณต์œ  ์˜์—ญ โ˜…       โ”‚
โ”‚      โ†‘              โ”‚
โ”‚ Heap (๊ณต์œ )         โ”‚  โ† ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๊ฐ์ฒด์— ์ ‘๊ทผ ๊ฐ€๋Šฅ
โ”‚ Data (๊ณต์œ )         โ”‚  โ† ์ „์—ญ ๋ณ€์ˆ˜๋„ ๊ณต์œ 
โ”‚ Code (๊ณต์œ )         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โ†’ ์Šค๋ ˆ๋“œ ๊ฐ„ ํ†ต์‹ ์€ ์ž์—ฐ์Šค๋Ÿฝ๋‹ค(๊ฐ™์€ ํž™ยท๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ƒฅ ์ฝ๊ณ  ์“ฐ๋ฉด ๋จ). ๋‹จ, ๊ทธ ์ž์—ฐ์Šค๋Ÿฌ์›€์ด race condition์˜ ์›์ธ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

PCB vs TCB

ํ•ญ๋ชฉPCB (Process Control Block)TCB (Thread Control Block)
์ €์žฅ ์œ„์น˜OS ์ปค๋„ (ํ”„๋กœ์„ธ์Šค ํ…Œ์ด๋ธ”)OS ์ปค๋„ (์Šค๋ ˆ๋“œ ํ…Œ์ด๋ธ”)
์‹๋ณ„์žPIDTID
๋ฉ”๋ชจ๋ฆฌ ์ •๋ณดํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šค, ๋ฉ”๋ชจ๋ฆฌ๋งต, ์ฝ”๋“œ/๋ฐ์ดํ„ฐ/ํž™ ์˜์—ญ ์ •๋ณด(์—†์Œ โ€” ํ”„๋กœ์„ธ์Šค์˜ PCB ์ฐธ์กฐ)
CPU ์ปจํ…์ŠคํŠธ(์Šค๋ ˆ๋“œ๋“ค์˜ ์ปจํ…์ŠคํŠธ ๋ชจ์Œ)PC, SP, ๋ฒ”์šฉ ๋ ˆ์ง€์Šคํ„ฐ
ํ•ธ๋“คยท์ž์›ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ, ์†Œ์ผ“, ํ™˜๊ฒฝ ๋ณ€์ˆ˜(์—†์Œ โ€” ํ”„๋กœ์„ธ์Šค์˜ PCB ๊ณต์œ )
๋ถ€๋ชจ/์ž์‹๋ถ€๋ชจ PID, ์ž์‹ PID ๋ฆฌ์ŠคํŠธ(ํ•ด๋‹น ์—†์Œ)
์Šค์ผ€์ค„๋ง ์ •๋ณด์šฐ์„ ์ˆœ์œ„, ์ƒํƒœ(Ready/Running/Wait)์Šค๋ ˆ๋“œ๋ณ„ ์šฐ์„ ์ˆœ์œ„ยท์ƒํƒœ
ํฌ๊ธฐํผ (์ˆ˜ KB)์ž‘์Œ (์ˆ˜๋ฐฑ ๋ฐ”์ดํŠธ)

โ†’ TCB๊ฐ€ ํ›จ์”ฌ ์ž‘๊ณ  ๊ฐ€๋ฒผ์šด ๊ฒŒ ์Šค๋ ˆ๋“œ ์ƒ์„ฑยท์ „ํ™˜ ๋น„์šฉ์ด ๋‚ฎ์€ ์ง์ ‘์  ์ด์œ ์ž…๋‹ˆ๋‹ค.

Linux์˜ task_struct (์ฐธ๊ณ )

Linux๋Š” ์‚ฌ์‹ค ํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ™์€ task_struct๋กœ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ง€ clone() ํ˜ธ์ถœ ์‹œ ์–ด๋–ค ์ž์›์„ ๊ณต์œ ํ• ์ง€ ํ”Œ๋ž˜๊ทธ๋กœ ์ง€์ •ํ•ด์„œ, ๋ชจ๋‘ ๊ณต์œ ํ•˜๋ฉด ์Šค๋ ˆ๋“œ์ฒ˜๋Ÿผ, ์•„๋ฌด๊ฒƒ๋„ ๊ณต์œ  ์•ˆ ํ•˜๋ฉด ํ”„๋กœ์„ธ์Šค์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

1
2
3
4
5
// Linux clone() ํ”Œ๋ž˜๊ทธ (์š”์•ฝ)
clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD, ...)
//    โ”” ๋ฉ”๋ชจ๋ฆฌ ๊ณต์œ  โ”˜  โ”” ํŒŒ์ผ์‹œ์Šคํ…œ โ”˜ โ”” FD ๊ณต์œ  โ”˜  โ”” ์‹œ๊ทธ๋„ โ”˜  โ”” ์Šค๋ ˆ๋“œ๊ทธ๋ฃน โ”˜
//    โ†’ ์œ„ ํ”Œ๋ž˜๊ทธ ๋‹ค ์ผœ๋ฉด "์Šค๋ ˆ๋“œ ์ƒ์„ฑ" (pthread_create ๋‚ด๋ถ€ ํ˜ธ์ถœ)
//    โ†’ ๋‹ค ๋„๋ฉด fork() (๋ณ„๊ฐœ ํ”„๋กœ์„ธ์Šค)

โ†’ โ€œํ”„๋กœ์„ธ์Šค/์Šค๋ ˆ๋“œ๋Š” OS ์ถ”์ƒํ™”์˜ ์–‘ ๋์ผ ๋ฟ ๋ณธ์งˆ์€ ๊ฐ™์€ task๋‹คโ€๋ผ๋Š” ๊ด€์ .


4. ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ โ€” ์™œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋น ๋ฅธ๊ฐ€

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

ํ”„๋กœ์„ธ์Šค ์ „ํ™˜์€ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๊ฐˆ์•„ํƒ€๋Š” ๋น„์šฉ(TLB flush + ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๊ต์ฒด + ์บ์‹œ cold start)์ด ์ถ”๊ฐ€๋กœ ๋“ค๊ณ , ์Šค๋ ˆ๋“œ ์ „ํ™˜์€ ๊ฐ™์€ ์ฃผ์†Œ ๊ณต๊ฐ„ ์•ˆ์ด๋ผ ๋ ˆ์ง€์Šคํ„ฐ๋งŒ ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์ด๋ž€

1
2
3
4
5
์‹คํ–‰ ํ๋ฆ„ A์—์„œ B๋กœ CPU๋ฅผ ๋„˜๊ธฐ๋Š” ๊ณผ์ •:
  โ‘  A์˜ CPU ๋ ˆ์ง€์Šคํ„ฐ(PC, SP, ๋ฒ”์šฉ)๋ฅผ A์˜ PCB/TCB์— ์ €์žฅ
  โ‘ก OS ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ B๋ฅผ ์„ ํƒ
  โ‘ข B์˜ PCB/TCB์—์„œ ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ๋ณต์› โ†’ CPU์— ๋กœ๋“œ
  โ‘ฃ B ์‹คํ–‰ ์žฌ๊ฐœ

ํ”„๋กœ์„ธ์Šค ์ „ํ™˜ ์ถ”๊ฐ€ ๋น„์šฉ

1
2
3
4
5
6
7
8
9
ํ”„๋กœ์„ธ์Šค A โ†’ B ์ „ํ™˜:
  [๊ณตํ†ต]
    โ‘  A ๋ ˆ์ง€์Šคํ„ฐ ์ €์žฅ
    โ‘ก B ๋ ˆ์ง€์Šคํ„ฐ ๋ณต์›
  [ํ”„๋กœ์„ธ์Šค ์ „ํ™˜๋งŒ ์ถ”๊ฐ€]
    โ‘ข ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šค ๋ ˆ์ง€์Šคํ„ฐ(x86: CR3) ๊ต์ฒด
    โ‘ฃ TLB flush (๋˜๋Š” ๋ถ€๋ถ„ ๋ฌดํšจํ™”)         โ˜… ํฐ ๋น„์šฉ
    โ‘ค ์งํ›„ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ = TLB miss โ†’ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์›Œํฌ
    โ‘ฅ L1ยทL2 ์บ์‹œ๋„ ์ฐจ๊ฐ€์›€ (cache cold)     โ˜… ํฐ ๋น„์šฉ

์Šค๋ ˆ๋“œ ์ „ํ™˜ (๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ์•ˆ)

1
2
3
4
5
6
์Šค๋ ˆ๋“œ X โ†’ Y ์ „ํ™˜ (๊ฐ™์€ ํ”„๋กœ์„ธ์Šค P ์•ˆ):
  โ‘  X ๋ ˆ์ง€์Šคํ„ฐ ์ €์žฅ
  โ‘ก Y ๋ ˆ์ง€์Šคํ„ฐ ๋ณต์›
  โ†’ ๋!
  TLBยทํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”ยท์บ์‹œ ๋ชจ๋‘ ๊ทธ๋Œ€๋กœ
  (์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™์€ ๊ณต์œ ๋ผ ์บ์‹œ ๋ผ์ธ์ด ์˜๋ฏธ ์žˆ๊ฒŒ ๋‚จ์•„์žˆ์Œ)

๋น„์šฉ ์ฐจ์ด (๋Œ€๋žต์ ์ธ ์ˆ˜์น˜)

์ž‘์—…์‹œ๊ฐ„ (์ฐธ๊ณ ์น˜)
ํ•จ์ˆ˜ ํ˜ธ์ถœ~1 ns
L1 ์บ์‹œ ์ ‘๊ทผ~1 ns
L2 ์บ์‹œ ์ ‘๊ทผ~5 ns
๋ฉ”์ธ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ~100 ns
์‹œ์Šคํ…œ ์ฝœ~500~1000 ns
์Šค๋ ˆ๋“œ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ~1~10 ฮผs
ํ”„๋กœ์„ธ์Šค ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ~5~50 ฮผs (TLBยท์บ์‹œ ์˜ํ–ฅ ํฌํ•จ ์‹œ ๋” ํผ)

โ†’ ๋‹จ์ˆœ ๋ ˆ์ง€์Šคํ„ฐ ๊ตํ™˜๋งŒ ๋ณด๋ฉด ๋‘˜ ๋‹ค ๋งˆ์ดํฌ๋กœ์ดˆ ๋‹จ์œ„์ง€๋งŒ, TLBยท์บ์‹œ ํšจ๊ณผ๊นŒ์ง€ ํฌํ•จํ•˜๋ฉด ํ”„๋กœ์„ธ์Šค ์ „ํ™˜์€ ์ˆ˜์‹ญ ฮผs๊นŒ์ง€ ๋Š˜์–ด๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒŒ์ž„ ์—”์ง„์ฒ˜๋Ÿผ 16.6ms(60fps) ์•ˆ์— ์ „๋ถ€ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ํ™˜๊ฒฝ์—์„  ์ด ์ฐจ์ด๊ฐ€ ๊ฒฐ์ •์ ์ž…๋‹ˆ๋‹ค.

TLB์™€ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” (๊ฐ„๋‹จํžˆ)

1
2
3
4
5
6
7
๊ฐ€์ƒ ์ฃผ์†Œ โ†’ ๋ฌผ๋ฆฌ ์ฃผ์†Œ ๋ณ€ํ™˜ ํ๋ฆ„:
  โ‘  CPU๊ฐ€ ๊ฐ€์ƒ ์ฃผ์†Œ ๋ฐœํ–‰
  โ‘ก TLB์—์„œ ๋งคํ•‘ ๊ฒ€์ƒ‰ (์บ์‹œ hit์ด๋ฉด ์ฆ‰์‹œ)
  โ‘ข TLB miss โ†’ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์›Œํฌ (4๋‹จ๊ณ„ โ€” x86_64) โ†’ ์ˆ˜์‹ญ ns
  โ‘ฃ ๊ฒฐ๊ณผ๋ฅผ TLB์— ์ ์žฌ

TLB flush: ์œ„ ์บ์‹œ๋ฅผ ํ†ต์งธ๋กœ ๋ฌดํšจํ™” โ†’ ํ•œ๋™์•ˆ ๋งค๋ฒˆ page walk

โ†’ ๊ทธ๋ž˜์„œ ํ”„๋กœ์„ธ์Šค ์ „ํ™˜ ์งํ›„์— ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€๋Š” ์‹œ๊ธฐ(์›Œ๋ฐ์—…)๊ฐ€ ์ž ๊น ์žˆ์Šต๋‹ˆ๋‹ค.

๋น„๊ต ํ‘œ

ํ•ญ๋ชฉํ”„๋กœ์„ธ์Šค ์ „ํ™˜์Šค๋ ˆ๋“œ ์ „ํ™˜ (๊ฐ™์€ ํ”„๋กœ์„ธ์Šค)
๋ ˆ์ง€์Šคํ„ฐ ์ €์žฅ/๋ณต์›โœ…โœ…
ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๊ต์ฒดโœ… (CR3)โŒ
TLB flushโœ… ๋˜๋Š” ๋ถ€๋ถ„ ๋ฌดํšจํ™”โŒ
L1ยทL2 ์บ์‹œ ์˜ํ–ฅํผ (cold)์ž‘์Œ (warm ์œ ์ง€)
๋น„์šฉ (์‹ค์ธก ๋Œ€๋žต)~5~50 ฮผs~1~10 ฮผs
ํ†ต์‹  ๋น„์šฉ๋„IPC (์ถ”๊ฐ€)๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ (์ถ”๊ฐ€ ๋น„์šฉ 0)

5. ํ†ต์‹  ๋ฐฉ์‹ โ€” IPC vs ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

ํ”„๋กœ์„ธ์Šค๋ผ๋ฆฌ๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ฒฉ๋ฆฌ๋ผ ์žˆ์–ด ๋ช…์‹œ์  IPC ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ํ•„์š”ํ•˜๊ณ , ์Šค๋ ˆ๋“œ๋ผ๋ฆฌ๋Š” ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ณด๊ณ  ์žˆ์–ด ๊ทธ๋ƒฅ ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค(๋Œ€์‹  ๋™๊ธฐํ™” ํ•„์š”).

IPC (Inter-Process Communication) ์ข…๋ฅ˜

๋ฐฉ์‹์„ค๋ช…์†๋„์šฉ๋„
ํŒŒ์ดํ”„ (anonymous pipe)๋ถ€๋ชจ-์ž์‹ ๋‹จ๋ฐฉํ–ฅ ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ๋ณดํ†ต์…ธ | ๊ฐ™์€ ๋‹จ์ˆœ ์—ฐ๊ฒฐ
named pipe (FIFO)ํŒŒ์ผ ์‹œ์Šคํ…œ์— ์ด๋ฆ„ ๊ฐ€์ง„ ํŒŒ์ดํ”„๋ณดํ†ต๋ฌด๊ด€ํ•œ ํ”„๋กœ์„ธ์Šค ๊ฐ„
๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ (shared memory)๊ฐ™์€ ๋ฌผ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋งคํ•‘๋น ๋ฆ„ (๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์†๋„)DBยท๊ณ ์„ฑ๋Šฅ IPC
๋ฉ”์‹œ์ง€ ํ (POSIX/SysV)์ปค๋„์ด ๊ด€๋ฆฌํ•˜๋Š” ๋ฉ”์‹œ์ง€ ๋ฒ„ํผ๋ณดํ†ต๋น„๋™๊ธฐ ๋ฉ”์‹œ์ง€
์„ธ๋งˆํฌ์–ด (semaphore)IPC์šฉ ๋™๊ธฐํ™” (๊ฐ’ ๊ธฐ๋ฐ˜)๋น ๋ฆ„๋‹ค๋ฅธ IPC์™€ ๋ณ‘ํ–‰
์‹œ๊ทธ๋„ (signal)๋น„๋™๊ธฐ ์•Œ๋ฆผ (SIGINT ๋“ฑ)๋น ๋ฆ„์ข…๋ฃŒยท์ธํ„ฐ๋ŸฝํŠธ ์•Œ๋ฆผ
์†Œ์ผ“ (Unix domain / TCP)์–‘๋ฐฉํ–ฅ ์ŠคํŠธ๋ฆผ. ๋„คํŠธ์›Œํฌ๋„ OK๋А๋ฆผ~๋ณดํ†ต๋ถ„๋ฆฌ๋œ ํ”„๋กœ์„ธ์Šคยท๋‹ค๋ฅธ ๋จธ์‹ 
๋ฉ”๋ชจ๋ฆฌ ๋งคํ•‘ (mmap)ํŒŒ์ผ์„ ๋ฉ”๋ชจ๋ฆฌ๋กœ ๋งคํ•‘๋น ๋ฆ„ํŒŒ์ผ ๊ณต์œ ยท๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ

์Šค๋ ˆ๋“œ ๊ฐ„ โ€œํ†ต์‹ โ€

1
2
3
4
5
6
7
8
9
10
11
12
// ์ „์—ญ ๋ณ€์ˆ˜ โ€” ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๊ณต์œ 
int counter = 0;

void Worker() {
    counter++;   // ๊ทธ๋ƒฅ ์ ‘๊ทผ. ๋ณ„๋„ IPC ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๋ถˆํ•„์š”.
}

// ํž™ ๊ฐ์ฒด ๊ณต์œ 
auto data = std::make_shared<std::vector<int>>();
std::thread t1([data]{ data->push_back(1); });
std::thread t2([data]{ data->push_back(2); });
// ๊ฐ™์€ vector๋ฅผ ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•จ๊ป˜ ๋ด„

โ†’ ์ด๊ฒŒ ๋น ๋ฅด๊ณ  ์ž์—ฐ์Šค๋Ÿฌ์šด๋ฐ, ๊ทธ๋ž˜์„œ race condition ์œ„ํ—˜์ด ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค.

๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ IPC vs ์Šค๋ ˆ๋“œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต์œ  โ€” ๋น„์Šทํ•˜์ง€๋งŒ ๋‹ค๋ฆ„

1
2
3
4
5
6
๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ IPC: ๋‘ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ๊ฐ™์€ ๋ฌผ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ์ž๊ธฐ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์— ๋งคํ•‘
                 (shmget/shmat ๋˜๋Š” mmap ์‚ฌ์šฉ)
                 โ†’ ๊ฒฉ๋ฆฌ๋Š” ๊นจ์ง€์ง€๋งŒ, ๋ช…์‹œ์  ์„ค์ •์ด ํ•„์š”

์Šค๋ ˆ๋“œ ๊ณต์œ :    ํ”„๋กœ์„ธ์Šค ์•ˆ์˜ ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ๊ฐ™์€ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๋ณธ๋‹ค
                 โ†’ ๋ณ„๋„ ์„ค์ • 0

๋น„์šฉยท์•ˆ์ „์„ฑ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„

ํ†ต์‹  ๋ฐฉ์‹์†๋„๊ฒฉ๋ฆฌ๋™๊ธฐํ™” ํ•„์š”
์†Œ์ผ“ (TCP)๋А๋ฆผ๊ฐ•ํ•จ (๋‹ค๋ฅธ ๋จธ์‹ ๋„ OK)ํ”„๋กœํ† ์ฝœ ์ž์ฒด๋กœ
ํŒŒ์ดํ”„ยท๋ฉ”์‹œ์ง€ ํ๋ณดํ†ต๊ฐ•ํ•จ์ปค๋„์ด ๋ณด์žฅ
๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ IPC๋น ๋ฆ„์•ฝํ•จ (๋ช…์‹œ์  ๋งคํ•‘)์ˆ˜๋™ (mutex ๋“ฑ)
์Šค๋ ˆ๋“œ ๊ณต์œ  ๋ณ€์ˆ˜๊ฐ€์žฅ ๋น ๋ฆ„์—†์Œ์ˆ˜๋™ (๋ฐ˜๋“œ์‹œ)

โ†’ โ€œ๊ฒฉ๋ฆฌ๋ฅผ ํฌ๊ธฐํ• ์ˆ˜๋ก ๋น ๋ฅด๋‹คโ€๋Š” ์ผ๊ด€๋œ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„. ๊ฒŒ์ž„ ์—”์ง„์ฒ˜๋Ÿผ ๋งค ํ”„๋ ˆ์ž„ ์ˆ˜๋งŒ ๊ฐœ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ค„์•ผ ํ•˜๋Š” ํ™˜๊ฒฝ์€ ๊ฒฉ๋ฆฌ๋ฅผ ํฌ๊ธฐํ•˜๊ณ  ์Šค๋ ˆ๋“œ ๊ณต์œ ๋ฅผ ์„ ํƒํ•  ์ˆ˜๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค.


6. ๋™๊ธฐํ™” ๋ฌธ์ œ โ€” race condition / mutex / deadlock

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

๊ณต์œ  ๋ฐ์ดํ„ฐ๋ฅผ ๋‘ ๊ฐœ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ non-atomicํ•œ ์—ฐ์‚ฐ์œผ๋กœ ๋™์‹œ ์ ‘๊ทผํ•˜๋ฉด race condition์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํ•ด๊ฒฐ์ฑ…์€ ์ž„๊ณ„ ๊ตฌ์—ญ์„ ํ•œ ๋ฒˆ์— ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ์‹คํ–‰ํ•˜๋„๋ก mutex ๋“ฑ์œผ๋กœ ๋ณดํ˜ธํ•˜๋Š” ๊ฒƒ์ด๊ณ , ๊ทธ ๊ณผ์ •์—์„œ deadlock ๊ฐ™์€ ์ƒˆ๋กœ์šด ๋ฌธ์ œ๊ฐ€ ๋”ฐ๋ผ์˜ต๋‹ˆ๋‹ค.

Race Condition ์‹œ๊ฐํ™”

1
2
int counter = 0;            // ์ „์—ญ ๊ณต์œ 
void Inc() { counter++; }   // ํ•œ ์ค„ ๊ฐ™์ง€๋งŒ ์‹ค์€ 3๋‹จ๊ณ„

counter++ ์˜ ๊ธฐ๊ณ„์–ด ์ˆ˜์ค€:

1
2
3
load   counter, R1   ; R1 โ† counter
add    R1, 1, R1     ; R1 โ† R1 + 1
store  R1, counter   ; counter โ† R1

๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ์ธํ„ฐ๋ฆฌ๋น™๋˜๋ฉด:

1
2
3
4
5
6
7
์‹œ๊ฐ„  ์Šค๋ ˆ๋“œ A           ์Šค๋ ˆ๋“œ B           counter ๋ฉ”๋ชจ๋ฆฌ
  1   load(0) โ†’ A.R1=0
  2                      load(0) โ†’ B.R1=0
  3   add โ†’ A.R1=1
  4                      add โ†’ B.R1=1
  5   store(1)                              counter = 1
  6                      store(1)           counter = 1   โ˜… ์žƒ์–ด๋ฒ„๋ฆฐ ๊ฐฑ์‹ 

โ†’ Inc()๋ฅผ ๋‘ ๋ฒˆ ํ–ˆ๋Š”๋ฐ counter๊ฐ€ 2๊ฐ€ ์•„๋‹Œ 1. ์ด๊ฒŒ lost update ํ˜•ํƒœ์˜ race condition.

์ž„๊ณ„ ๊ตฌ์—ญ (Critical Section)

1
2
3
4
5
6
์ž„๊ณ„ ๊ตฌ์—ญ = ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•˜๋Š” ์ฝ”๋“œ ๊ตฌ๊ฐ„
ํ•„์š”ํ•œ 4๊ฐ€์ง€ ๋ณด์žฅ:
  โ‘  ์ƒํ˜ธ ๋ฐฐ์ œ (Mutual Exclusion) โ€” ํ•œ ๋ฒˆ์— ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ์ง„์ž…
  โ‘ก ์ง„ํ–‰ (Progress)               โ€” ์•„๋ฌด๋„ ์•ˆ ์“ฐ๋ฉด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์–ด์•ผ
  โ‘ข ํ•œ๊ณ„ ๋Œ€๊ธฐ (Bounded Wait)      โ€” ๋ฌดํ•œ์ • ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š์•„์•ผ
  โ‘ฃ ๊ฐ€์ • ์—†์Œ                     โ€” CPU ์†๋„ยท๊ฐœ์ˆ˜์— ์˜์กดํ•˜์ง€ ๋ง ๊ฒƒ

Mutex (Mutual Exclusion)

1
2
3
4
5
6
7
8
std::mutex m;
int counter = 0;

void Inc() {
    m.lock();
    counter++;       // ์ž„๊ณ„ ๊ตฌ์—ญ โ€” ํ•œ ๋ฒˆ์— ํ•œ ์Šค๋ ˆ๋“œ๋งŒ
    m.unlock();
}

๋ฌธ์ œ: counter++์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋‚˜๋ฉด unlock()์ด ์•ˆ ํ˜ธ์ถœ๋ผ deadlock. ์ด๊ฑธ RAII๋กœ ์ž๋™ํ™”ํ•œ ๊ฒŒ std::lock_guard (9๋ฒˆ RAII์˜ ๋™์‹œ์„ฑ ์‘์šฉ).

1
2
3
4
void IncSafe() {
    std::lock_guard<std::mutex> lock(m);  // ์ƒ์„ฑ ์‹œ lock
    counter++;                            // ์˜ˆ์™ธ ๋‚˜๋„ OK
}                                         // ์†Œ๋ฉธ ์‹œ ์ž๋™ unlock

โ†’ Community 18 (Mutex ๋ฝ โ€” lock_guardยทscopedยทunique)๊ณผ Community 23 (std::mutex ๋ณต์‚ฌยท์ด๋™ ๊ธˆ์ง€)์ด ์ •ํ™•ํžˆ ์ด ์˜์—ญ.

Deadlock โ€” 4๊ฐ€์ง€ ์กฐ๊ฑด (Coffman conditions)

๋„ค ์กฐ๊ฑด์ด ๋™์‹œ์— ๋งŒ์กฑ๋ผ์•ผ deadlock ๋ฐœ์ƒ. ํ•˜๋‚˜๋ผ๋„ ๊นจ๋ฉด deadlock ํšŒํ”ผ ๊ฐ€๋Šฅ.

์กฐ๊ฑด์„ค๋ช…
โ‘  ์ƒํ˜ธ ๋ฐฐ์ œ (Mutual Exclusion)์ž์›์„ ํ•œ ๋ฒˆ์— ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ์ ์œ 
โ‘ก ์ ์œ ์™€ ๋Œ€๊ธฐ (Hold and Wait)์ž์›์„ ๋“  ์ฑ„ ๋‹ค๋ฅธ ์ž์›์„ ๊ธฐ๋‹ค๋ฆผ
โ‘ข ๋น„์„ ์  (No Preemption)OS๊ฐ€ ๊ฐ•์ œ๋กœ ์ž์›์„ ๋นผ์•—์„ ์ˆ˜ ์—†์Œ
โ‘ฃ ์ˆœํ™˜ ๋Œ€๊ธฐ (Circular Wait)์Šค๋ ˆ๋“œ๋“ค์ด ์›ํ˜•์œผ๋กœ ์ž์›์„ ๊ธฐ๋‹ค๋ฆผ

Deadlock ์‹œ๊ฐํ™”

1
2
3
4
5
6
7
8
9
10
11
12
13
std::mutex A, B;

void T1() {
    std::lock_guard<std::mutex> la(A);
    std::this_thread::sleep_for(1ms);
    std::lock_guard<std::mutex> lb(B);  // B๊ฐ€ T2์— ์žกํ˜€์žˆ์œผ๋ฉด ์˜์›ํžˆ ๋Œ€๊ธฐ
}

void T2() {
    std::lock_guard<std::mutex> lb(B);
    std::this_thread::sleep_for(1ms);
    std::lock_guard<std::mutex> la(A);  // A๊ฐ€ T1์— ์žกํ˜€์žˆ์œผ๋ฉด ์˜์›ํžˆ ๋Œ€๊ธฐ
}
1
2
3
T1: A ์žก์Œ โ†’ B ๊ธฐ๋‹ค๋ฆผ
T2: B ์žก์Œ โ†’ A ๊ธฐ๋‹ค๋ฆผ
   โ†ป ์ˆœํ™˜ ๋Œ€๊ธฐ โ†’ ๋‘˜ ๋‹ค ๋ฉˆ์ถค

Deadlock ํšŒํ”ผ ํŒจํ„ด

1
2
3
4
5
6
7
8
9
10
11
12
13
1. ๋ฝ ์ˆœ์„œ ์ •ํ•˜๊ธฐ (Lock Ordering)
   - ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ํ•ญ์ƒ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๋ฝ์„ ํš๋“ (์˜ˆ: ์ฃผ์†Œ ์˜ค๋ฆ„์ฐจ์ˆœ)
   โ†’ ์ˆœํ™˜ ๋Œ€๊ธฐ ๊นจ์ง

2. std::scoped_lock (C++17) โ€” ์—ฌ๋Ÿฌ mutex ๋™์‹œ์— ํš๋“
   std::scoped_lock lk(A, B);  // ๋ฐ๋“œ๋ฝ ํšŒํ”ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋‚ด์žฅ

3. try_lock + ๋ฐฑ์˜คํ”„
   - ๋ฝ์„ ๋ชป ์žก์œผ๋ฉด ๊ฐ€์ง€๊ณ  ์žˆ๋˜ ๋ฝ ํ’€๊ณ  ์žฌ์‹œ๋„
   โ†’ ์ ์œ ์™€ ๋Œ€๊ธฐ ๊นจ์ง

4. ๋ฝ ๊ณ„์ธต (Lock Hierarchy)
   - ๋ฝ์— ๋ ˆ๋ฒจ์„ ๋ถ€์—ฌ, ๋†’์€ ๋ ˆ๋ฒจ์—์„œ ๋‚ฎ์€ ๋ ˆ๋ฒจ ๋ฝ๋งŒ ํš๋“ ๊ฐ€๋Šฅ

๋‹ค๋ฅธ ๋™์‹œ์„ฑ ๋ฌธ์ œ๋“ค

๋ฌธ์ œ์„ค๋ช…์˜ˆ์‹œ
Race condition๋™์‹œ ์ ‘๊ทผ์œผ๋กœ ๊ฒฐ๊ณผ ๋น„๊ฒฐ์ •์ counter++
Deadlock์„œ๋กœ์˜ ๋ฝ์„ ๋ฌดํ•œ ๋Œ€๊ธฐ์œ„ T1/T2
Livelock๋‹ค๋“ค ์–‘๋ณด๋งŒ ํ•˜๋‹ค๊ฐ€ ์ง„ํ–‰ ์•ˆ ๋จ๋‘ ์‚ฌ๋žŒ์ด ๋ณต๋„์—์„œ ๊ณ„์† ๊ฐ™์€ ๋ฐฉํ–ฅ์œผ๋กœ ๋น„ํ‚ด
StarvationํŠน์ • ์Šค๋ ˆ๋“œ๊ฐ€ ์˜์›ํžˆ ์ž์› ๋ชป ๋ฐ›์Œ์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์•„์„œ ๋งค๋ฒˆ ๋ฐ€๋ฆผ
Priority Inversion๋‚ฎ์€ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋ฝ์„ ๋“ค๊ณ , ๋†’์€ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๊ธฐ๋‹ค๋ฆผNASA Mars Pathfinder ์‚ฌ๋ก€

Atomic โ€” Lock-Free ๋Œ€์•ˆ

1
2
3
4
5
6
std::atomic<int> counter{0};

void Inc() {
    counter.fetch_add(1);  // CPU ๋ช…๋ น์–ด๋กœ ์›์ž์  ๋ณด์žฅ (LOCK XADD ๋“ฑ)
    // ๋˜๋Š” counter++; (์˜ค๋ฒ„๋กœ๋”ฉ๋จ)
}

โ†’ ๋‹จ์ˆœํ•œ read-modify-write๋Š” mutex๋ณด๋‹ค atomic์ด ํ›จ์”ฌ ๋น ๋ฆ„. 11๋ฒˆ์—์„œ ๋ณธ shared_ptr ์ œ์–ด ๋ธ”๋ก์˜ reference counter๋„ atomic์œผ๋กœ ๊ตฌํ˜„๋จ.


7. ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค vs ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ โ€” ์–ธ์ œ ๋ฌด์—‡์„ ์“ฐ๋‚˜

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

๊ฒฉ๋ฆฌยท์•ˆ์ •์„ฑยท๋ณด์•ˆ์ด ์šฐ์„ ์ด๋ฉด ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค, ์†๋„ยทํ†ต์‹  ๋นˆ๋„ยท์ž์› ํšจ์œจ์ด ์šฐ์„ ์ด๋ฉด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ.

๋น„๊ต ํ‘œ

๊ด€์ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ
๋ฉ”๋ชจ๋ฆฌ ๊ฒฉ๋ฆฌ๊ฐ•ํ•จ (๋‹ค๋ฅธ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„)์—†์Œ (๊ฐ™์€ ๊ณต๊ฐ„)
ํ•œ์ชฝ ํฌ๋ž˜์‹œ ์˜ํ–ฅ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค ์˜ํ–ฅ X์ „์ฒด ํ”„๋กœ์„ธ์Šค ๋‹ค์šด
์ƒ์„ฑ ๋น„์šฉํผ (fork/CreateProcess)์ž‘์Œ (pthread_create/std::thread)
์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ๋น„์Œˆ (TLBยทํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”)์‹ผ ํŽธ
ํ†ต์‹  ๋น„์šฉIPC โ€” ๋น„์Œˆ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ โ€” 0
๋™๊ธฐํ™” ๋ถ€๋‹ด๋‚ฎ์Œ (์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฒฉ๋ฆฌ)๋†’์Œ (mutex ๋“ฑ ํ•„์ˆ˜)
๋””๋ฒ„๊น… ๋‚œ์ด๋„๋น„๊ต์  ์‰ฌ์›€ (๊ฒฉ๋ฆฌ)์–ด๋ ค์›€ (race condition ์žฌํ˜„ ์–ด๋ ค์›€)
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ํผ (๊ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ž๊ธฐ ์˜์—ญ)์ž‘์Œ (๋Œ€๋ถ€๋ถ„ ๊ณต์œ )
๋ณด์•ˆ ๊ฒฉ๋ฆฌ๊ฐ•ํ•จ์—†์Œ

์‚ฌ๋ก€ ๋ถ„์„

Chrome โ€” ํƒญ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Chrome ์•„ํ‚คํ…์ฒ˜:
  โ”Œโ”€ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ์„ธ์Šค (UIยท๋„คํŠธ์›Œํฌยท๋””์Šคํฌ I/O)
  โ”œโ”€ ๋ Œ๋”๋Ÿฌ ํ”„๋กœ์„ธ์Šค 1 (ํƒญ 1) โ† ํƒญ 1์ด ํฌ๋ž˜์‹œํ•ด๋„ ๋‹ค๋ฅธ ํƒญ ์•ˆ ์ฃฝ์Œ
  โ”œโ”€ ๋ Œ๋”๋Ÿฌ ํ”„๋กœ์„ธ์Šค 2 (ํƒญ 2)
  โ”œโ”€ GPU ํ”„๋กœ์„ธ์Šค
  โ””โ”€ ํ”Œ๋Ÿฌ๊ทธ์ธ ํ”„๋กœ์„ธ์Šค

์ด์œ :
  โ‘  ๋ณด์•ˆ โ€” ์•…์„ฑ ์‚ฌ์ดํŠธ๊ฐ€ ๋‹ค๋ฅธ ํƒญ์˜ ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผ ๋ชป ํ•จ (sandbox)
  โ‘ก ์•ˆ์ •์„ฑ โ€” ํ•œ ํƒญ ํฌ๋ž˜์‹œ = ๊ทธ ํƒญ๋งŒ ์ข…๋ฃŒ
  โ‘ข ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๊ฒฉ๋ฆฌ โ€” ํƒญ ๋‹ซ์œผ๋ฉด ๊ทธ ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ ์ „๋ถ€ ํšŒ์ˆ˜
๋Œ€๊ฐ€:
  - ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ (ํƒญ๋งˆ๋‹ค ์ˆ˜์‹ญ MB ๋ฒ ์ด์Šค)
  - IPC ๋น„์šฉ (๋ธŒ๋ผ์šฐ์ € โ†” ๋ Œ๋”๋Ÿฌ ํ†ต์‹ )

PostgreSQL โ€” ์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค (์ „ํ†ต์ )

1
2
3
4
5
6
7
์ƒˆ ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ โ†’ fork() โ†’ ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ทธ ์—ฐ๊ฒฐ ์ฒ˜๋ฆฌ
์ด์œ :
  โ‘  ํ•œ ์ฟผ๋ฆฌ๊ฐ€ ์ฃฝ์–ด๋„ ๋‹ค๋ฅธ ์—ฐ๊ฒฐ ์˜ํ–ฅ X
  โ‘ก ๋ฉ”๋ชจ๋ฆฌ ๊ฒฉ๋ฆฌ (๋ณด์•ˆ)
๋Œ€๊ฐ€:
  - fork ๋น„์šฉ (Postgres๊ฐ€ connection pooling์„ ๊ถŒ์žฅํ•˜๋Š” ์ด์œ )
  - ๊ณต์œ  ๋ฐ์ดํ„ฐ๋Š” shared memory๋กœ ๋”ฐ๋กœ ๊ด€๋ฆฌ

Apache vs Nginx

1
2
3
4
5
Apache (์ „ํ†ต prefork): ์—ฐ๊ฒฐ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค โ€” ์•ˆ์ •์ ์ด๋‚˜ ๋ฌด๊ฑฐ์›€
Apache (worker MPM):   ํ”„๋กœ์„ธ์Šค + ์Šค๋ ˆ๋“œ ํ˜ผํ•ฉ
Nginx:                 ์ด๋ฒคํŠธ ๋ฃจํ”„ + ์›Œ์ปค ํ”„๋กœ์„ธ์Šค (์ ์€ ์ˆ˜) โ€” ํšจ์œจ์ 

์„ ํƒ ๊ธฐ์ค€์€ ๋™์‹œ ์ ‘์† ๊ทœ๋ชจ์™€ ๊ฒฉ๋ฆฌ ์š”๊ตฌ.

๊ฒŒ์ž„ ์—”์ง„ โ€” ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ

1
2
3
4
5
6
7
8
9
์ด์œ :
  โ‘  ๋งค ํ”„๋ ˆ์ž„ 16.6ms (60fps) โ€” IPC ๋น„์šฉ์„ ๊ฒฌ๋”œ ์ˆ˜ ์—†์Œ
  โ‘ก ๊ฒŒ์ž„ ๊ฐ์ฒด ์ˆ˜๋งŒ ๊ฐœ๋ฅผ ๋งค ํ”„๋ ˆ์ž„ ์—…๋ฐ์ดํŠธ โ†’ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ํ•„์ˆ˜
  โ‘ข ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ(๋กœ์ง) โ†” ๋ Œ๋” ์Šค๋ ˆ๋“œ(GPU ๋ช…๋ น) ๋™๊ธฐํ™” ์ž์ฃผ

๋Œ€๊ฐ€:
  - race condition ์œ„ํ—˜ (mutexยทatomicยทlock-free ์ž๋ฃŒ๊ตฌ์กฐ ๋‹ค์ˆ˜)
  - ํ•œ ์Šค๋ ˆ๋“œ ํฌ๋ž˜์‹œ = ๊ฒŒ์ž„ ๋‹ค์šด
  - ๋””๋ฒ„๊น… ๋‚œ์ด๋„ (๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋””๋ฒ„๊ฑฐ ํ•„์ˆ˜)

์›น ์„œ๋ฒ„ ์›Œ์ปค (Node.js / ์›Œ์ปค ํ’€)

1
2
3
Node.js: ๋‹จ์ผ ์Šค๋ ˆ๋“œ + ์ด๋ฒคํŠธ ๋ฃจํ”„ (CPU ์ž‘์—…์€ worker_threads๋กœ ์œ„์ž„)
Java/Tomcat: ์Šค๋ ˆ๋“œ ํ’€ (์š”์ฒญ๋‹น ์Šค๋ ˆ๋“œ)
Go: ๊ณ ๋ฃจํ‹ด (M:N) โ€” ์Šค๋ ˆ๋“œ๋ณด๋‹ค ๋” ๊ฐ€๋ฒผ์šด ์ถ”์ƒํ™”

๊ฒฐ์ • ํ๋ฆ„

1
2
3
4
5
6
7
8
9
10
11
12
13
์š”์ฒญ ์ฒ˜๋ฆฌ/์ž‘์—… ์ข…๋ฅ˜๋Š”?
  โ”‚
  โ”œโ”€โ”€ ๊ฒฉ๋ฆฌยท๋ณด์•ˆ ์šฐ์„  (๋ธŒ๋ผ์šฐ์ € ํƒญ, DB ์—ฐ๊ฒฐ)
  โ”‚     โ””โ”€โ”€ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค
  โ”‚
  โ”œโ”€โ”€ ์งง์€ ๋นˆ๋„์˜ ๋ฌด๊ฑฐ์šด ํ†ต์‹  (๋ถ„์‚ฐ ์‹œ์Šคํ…œ)
  โ”‚     โ””โ”€โ”€ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค + IPC (๋˜๋Š” ๋„คํŠธ์›Œํฌ)
  โ”‚
  โ”œโ”€โ”€ ์žฆ์€ ํ†ต์‹ ยท๋‚ฎ์€ ์ง€์—ฐ (๊ฒŒ์ž„, ์›น ์„œ๋ฒ„ ์›Œ์ปค)
  โ”‚     โ””โ”€โ”€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ + ๋™๊ธฐํ™”
  โ”‚
  โ””โ”€โ”€ ๋งค์šฐ ๋งŽ์€ ๋™์‹œ ์ž‘์—… (์ˆ˜์‹ญ๋งŒ connection)
        โ””โ”€โ”€ async/await ๋˜๋Š” ์ฝ”๋ฃจํ‹ด (์ด๋ฒคํŠธ ๋ฃจํ”„ ๋ชจ๋ธ)

8. ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ vs ์ปค๋„ ์Šค๋ ˆ๋“œ โ€” 1:1 / N:1 / M:N ๋ชจ๋ธ

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ด€๋ฆฌ(๋น ๋ฆ„ยท์‹œ์Šคํ…œ ์ฝœ์— ์•ฝํ•จ), ์ปค๋„ ์Šค๋ ˆ๋“œ๋Š” OS๊ฐ€ ๊ด€๋ฆฌ(์‹œ์Šคํ…œ ์ฝœ ์ž์œ ยท์ƒ์„ฑ ๋น„์šฉ ํผ), ๊ทธ๋ฆฌ๊ณ  ๋‘˜์„ ์–ด๋–ป๊ฒŒ ๋งคํ•‘ํ•˜๋А๋ƒ๊ฐ€ 1:1 / N:1 / M:N ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž vs ์ปค๋„ ์Šค๋ ˆ๋“œ

ํ•ญ๋ชฉ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ์ปค๋„ ์Šค๋ ˆ๋“œ
๊ด€๋ฆฌ ์ฃผ์ฒด์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (์˜ˆ์ „ Java green thread)OS ์ปค๋„
์ƒ์„ฑ ๋น„์šฉ๋งค์šฐ ์ž‘์Œํผ (์‹œ์Šคํ…œ ์ฝœยท์ปค๋„ ์ž๋ฃŒ๊ตฌ์กฐ)
์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ๋น ๋ฆ„ (์ปค๋„ ์ง„์ž… X)๋น„์Œˆ (์ปค๋„ ๋ชจ๋“œ ์ „ํ™˜)
์‹œ์Šคํ…œ ์ฝœ ์ฐจ๋‹จ ์‹œ์ „์ฒด ํ”„๋กœ์„ธ์Šค ์ฐจ๋‹จ (์ปค๋„์€ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ ๋ชจ๋ฆ„)๊ทธ ์Šค๋ ˆ๋“œ๋งŒ ์ฐจ๋‹จ, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ ์ง„ํ–‰
๋ฉ€ํ‹ฐ ์ฝ”์–ด ํ™œ์šฉ์–ด๋ ค์›€์ž์—ฐ์Šค๋Ÿฌ์›€

1:1 ๋ชจ๋ธ (Linux pthread, Windows Thread, std::thread)

1
2
3
4
5
6
7
8
9
10
์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ 1๊ฐœ โ†” ์ปค๋„ ์Šค๋ ˆ๋“œ 1๊ฐœ

์žฅ์ :
  โ‘  ์‹œ์Šคํ…œ ์ฝœ ์ฐจ๋‹จํ•ด๋„ ๊ทธ ์Šค๋ ˆ๋“œ๋งŒ ์˜ํ–ฅ
  โ‘ก ๋ฉ€ํ‹ฐ ์ฝ”์–ด ํ™œ์šฉ ์ž์—ฐ์Šค๋Ÿฌ์›€
  โ‘ข ๋‹จ์ˆœํ•œ ๋งคํ•‘

๋‹จ์ :
  โ‘  ์ƒ์„ฑ ๋น„์šฉ ํผ
  โ‘ก ๋™์‹œ ์Šค๋ ˆ๋“œ ์ˆ˜์— OS ์ œํ•œ

โ†’ ํ˜„๋Œ€ OS์˜ ํ‘œ์ค€ (WindowsยทLinuxยทmacOS). C++ std::thread๋„ 1:1.

N:1 ๋ชจ๋ธ (์˜ˆ์ „ Java green thread, GNU Pth)

1
2
3
4
5
6
7
8
9
์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ โ†’ ์ปค๋„ ์Šค๋ ˆ๋“œ 1๊ฐœ

์žฅ์ :
  โ‘  ๋งค์šฐ ๊ฐ€๋ฒผ์›€ (์ปค๋„ ์ž๋ฃŒ๊ตฌ์กฐ 1๊ฐœ)
  โ‘ก ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋งค์šฐ ๋น ๋ฆ„

๋‹จ์ :
  โ‘  ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹œ์Šคํ…œ ์ฝœ ์ฐจ๋‹จ โ†’ ์ „๋ถ€ ์ฐจ๋‹จ
  โ‘ก ๋ฉ€ํ‹ฐ ์ฝ”์–ด ํ™œ์šฉ ๋ถˆ๊ฐ€

โ†’ ํ˜„๋Œ€์—” ๊ฑฐ์˜ ์•ˆ ์”€.

M:N ๋ชจ๋ธ (Go goroutine, Java Loom virtual thread)

1
2
3
4
5
6
7
8
9
10
M๊ฐœ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ โ†’ N๊ฐœ ์ปค๋„ ์Šค๋ ˆ๋“œ (M >> N)

์žฅ์ :
  โ‘  ๊ฐ€๋ฒผ์›€ (์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ์Šค์ผ€์ค„๋ง)
  โ‘ก ๋ฉ€ํ‹ฐ ์ฝ”์–ด ํ™œ์šฉ (์ปค๋„ ์Šค๋ ˆ๋“œ๊ฐ€ N๊ฐœ)
  โ‘ข ์‹œ์Šคํ…œ ์ฝœ ์ฐจ๋‹จ ์‹œ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ๋ฅผ ๋‹ค๋ฅธ ์ปค๋„ ์Šค๋ ˆ๋“œ์— ์žฌ๋ฐฐ์น˜

๋‹จ์ :
  โ‘  ๋Ÿฐํƒ€์ž„์ด ๋ณต์žก (์Šค์ผ€์ค„๋Ÿฌยท๋ธ”๋กœํ‚น ์ฒ˜๋ฆฌ)
  โ‘ก ๋””๋ฒ„๊น… ์–ด๋ ค์›€

โ†’ Go๋Š” ์ˆ˜๋งŒ ๊ฐœ ๊ณ ๋ฃจํ‹ด์„ 4~16๊ฐœ OS ์Šค๋ ˆ๋“œ ์œ„์—์„œ ๋Œ๋ฆฝ๋‹ˆ๋‹ค. Java๋„ 21์—์„œ virtual thread ๋„์ž….

์š”์•ฝ

1
2
3
1:1  โ€” std::thread, pthread, Windows Thread     (๊ฐ€์žฅ ์ผ๋ฐ˜)
N:1  โ€” ์˜ˆ์ „ Java green thread                    (์—ญ์‚ฌ์ )
M:N  โ€” Go goroutine, Java Loom virtual thread   (์ตœ์‹  ํŠธ๋ Œ๋“œ)

9. C++ ์ฝ”๋“œ ์˜ˆ์‹œ โ€” std::thread / mutex / async / atomic

9.1 std::thread โ€” ๊ฐ€์žฅ ๊ธฐ๋ณธ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <thread>

void Worker(int id) {
    std::cout << "Thread " << id << " running\n";
}

int main() {
    std::thread t1(Worker, 1);
    std::thread t2(Worker, 2);

    // ๋žŒ๋‹ค๋„ ๊ฐ€๋Šฅ
    std::thread t3([]{ std::cout << "lambda thread\n"; });

    t1.join();   // t1์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋ฉ”์ธ์ด ๋Œ€๊ธฐ
    t2.join();
    t3.join();
}

๋ฐ˜๋“œ์‹œ join() ๋˜๋Š” detach()๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•ˆ ํ•˜๋ฉด std::thread ์†Œ๋ฉธ์ž๊ฐ€ std::terminate() ํ˜ธ์ถœ โ€” ํ”„๋กœ์„ธ์Šค ๊ฐ•์ œ ์ข…๋ฃŒ.

9.2 std::mutex + std::lock_guard โ€” RAII ๋ฝ (9๋ฒˆ ํšŒ๊ท€)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <mutex>
#include <thread>
#include <vector>

std::mutex m;
int counter = 0;

void Inc(int times) {
    for (int i = 0; i < times; ++i) {
        std::lock_guard<std::mutex> lock(m);  // ์ƒ์„ฑ ์‹œ lock
        ++counter;                            // ์ž„๊ณ„ ๊ตฌ์—ญ
    }                                         // ์†Œ๋ฉธ ์‹œ ์ž๋™ unlock
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < 10; ++i)
        threads.emplace_back(Inc, 1000);
    for (auto& t : threads) t.join();
    std::cout << counter;   // ์ •ํ™•ํžˆ 10000
}

โ†’ lock_guard ์—†์ด m.lock()/m.unlock() ์ง์ ‘ ํ˜ธ์ถœํ•˜๋ฉด ์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ unlock ๋ˆ„๋ฝ โ†’ deadlock. 9๋ฒˆ RAII๊ฐ€ ๋™์‹œ์„ฑ์—์„œ๋„ ๊ทธ๋Œ€๋กœ ์ ์šฉ๋จ.

9.3 std::scoped_lock (C++17) โ€” ์—ฌ๋Ÿฌ mutex ๋™์‹œ์—

1
2
3
4
5
6
std::mutex a, b;

void Transfer(/* ... */) {
    std::scoped_lock lk(a, b);   // ๋‘˜ ๋‹ค ์•ˆ์ „ํ•˜๊ฒŒ lock (deadlock ํšŒํ”ผ)
    // ...
}

โ†’ ๋‘ mutex๋ฅผ ํ•ญ์ƒ ๊ฐ™์€ ์ˆœ์„œ๋กœ ์žก์ง€ ์•Š์•„๋„ ๋ฐ๋“œ๋ฝ์ด ์•ˆ ๋‚˜๋„๋ก ๋‚ด๋ถ€์ ์œผ๋กœ try_lock + back-off๋ฅผ ํ•จ.

9.4 std::async / std::future โ€” ๋น„๋™๊ธฐ ์ž‘์—…

1
2
3
4
5
6
7
8
9
10
11
12
#include <future>

int Compute() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 42;
}

int main() {
    std::future<int> f = std::async(std::launch::async, Compute);
    // ... ๋‹ค๋ฅธ ์ผ ํ•˜๋‹ค๊ฐ€
    int result = f.get();   // ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ๋ฐ›๊ธฐ
}

โ†’ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›๋Š” ๋ช…์‹œ์  ์ฑ„๋„์ด ์žˆ์–ด์„œ race condition ์—†์ด ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ.

9.5 std::atomic โ€” Lock-Free

1
2
3
4
5
6
7
8
9
#include <atomic>

std::atomic<int> counter{0};

void Inc(int times) {
    for (int i = 0; i < times; ++i)
        counter.fetch_add(1);   // ์›์ž์ 
        // ๋˜๋Š” counter++; (์˜ค๋ฒ„๋กœ๋”ฉ๋จ)
}

โ†’ ๋‹จ์ˆœ ์นด์šดํ„ฐ ์ฆ๊ฐ์€ mutex๋ณด๋‹ค atomic์ด 5~10๋ฐฐ ๋น ๋ฆ„. ๋‹จ, ๋ณต์žกํ•œ ์ž„๊ณ„ ๊ตฌ์—ญ(์—ฌ๋Ÿฌ ๋ณ€์ˆ˜ ๋™์‹œ ๋ณ€๊ฒฝ)์—” mutex ํ•„์š”.

9.6 condition_variable โ€” ์Šค๋ ˆ๋“œ ๊ฐ„ ์‹ ํ˜ธ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <condition_variable>

std::mutex m;
std::condition_variable cv;
bool ready = false;

void Producer() {
    {
        std::lock_guard<std::mutex> lock(m);
        ready = true;
    }
    cv.notify_one();   // ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ ๊นจ์›€
}

void Consumer() {
    std::unique_lock<std::mutex> lock(m);
    cv.wait(lock, []{ return ready; });   // ready==true๊ฐ€ ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
    // ์ž„๊ณ„ ๊ตฌ์—ญ ์ง„์ž… (lock ํš๋“ ์ƒํƒœ)
}

โ†’ Producer-Consumer ํŒจํ„ด, ์ž‘์—… ํ ๋“ฑ์— ํ•„์ˆ˜.

9.7 std::jthread (C++20) โ€” ์ž๋™ join + ํ˜‘์กฐ์  ์ทจ์†Œ

1
2
3
4
5
6
7
8
9
10
11
12
#include <thread>

void Worker(std::stop_token st, int id) {
    while (!st.stop_requested()) {
        // ...
    }
}

int main() {
    std::jthread jt(Worker, 1);
    // ๋ฉ”์ธ ์ข…๋ฃŒ ์‹œ ์ž๋™์œผ๋กœ stop_requested + join
}

โ†’ std::thread์˜ join ๋ˆ„๋ฝ ์‚ฌ๊ณ ๋ฅผ ๋ง‰๋Š” C++20 ๊ฐœ์„ ํŒ.


10. ์–ธ๋ฆฌ์–ผ์—์„œ์˜ ์Šค๋ ˆ๋“œ โ€” ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ / ๋ Œ๋” ์Šค๋ ˆ๋“œ / FRunnable

ํ•ต์‹ฌ ํ•œ ๋ฌธ์žฅ

์–ธ๋ฆฌ์–ผ ์—”์ง„์€ ๊ฒŒ์ž„ ๋กœ์ง๊ณผ ๋ Œ๋”๋ง์„ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋กœ ๋ถ„๋ฆฌํ•ด GPU์™€ CPU๋ฅผ ๋ณ‘๋ ฌ๋กœ ํ™œ์šฉํ•˜๊ณ , FRunnable/AsyncTask/ParallelFor๋กœ ์›Œ์ปค ์Šค๋ ˆ๋“œ๋ฅผ ์ถ”์ƒํ™”ํ•˜๋ฉฐ, RAII ๋ฝ FScopeLock์œผ๋กœ ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

10.1 ์–ธ๋ฆฌ์–ผ์˜ ์ฃผ์š” ์Šค๋ ˆ๋“œ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ (Game Thread / Main Thread)
  - AActor, AGameMode, UWorld ๋“ฑ ๋ชจ๋“  ๊ฒŒ์ž„ํ”Œ๋ ˆ์ด ๋กœ์ง
  - Tick(), ์ž…๋ ฅ ์ฒ˜๋ฆฌ, UI ๊ฐฑ์‹  (UMG)
  - "๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ์—์„œ๋งŒ UObjectยทAActor ์ ‘๊ทผ ๊ฐ€๋Šฅ" ์ด ๊ธฐ๋ณธ ๋ฃฐ

๋ Œ๋” ์Šค๋ ˆ๋“œ (Render Thread)
  - ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ๊ฐ€ ๋งŒ๋“  ๋ช…๋ น(์˜ˆ: Draw Indexed Primitive)์„ GPU ๋ช…๋ น์œผ๋กœ ๋ณ€ํ™˜
  - RHI(Rendering Hardware Interface) ํ˜ธ์ถœ
  - ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ์™€ 1ํ”„๋ ˆ์ž„ ์ •๋„ ๋Šฆ๊ฒŒ ์ง„ํ–‰ (์ง€์—ฐ ๋ Œ๋”๋ง)

RHI ์Šค๋ ˆ๋“œ / GPU ์Šค๋ ˆ๋“œ
  - ์‹ค์ œ GPU ๋ช…๋ น์–ด ๋””์ŠคํŒจ์น˜
  - ๋ Œ๋” ์Šค๋ ˆ๋“œ์˜ ๋ช…๋ น์„ ๋ฐ›์•„ ์ฒ˜๋ฆฌ

์›Œ์ปค ํ’€ (Task Graph / Async Tasks)
  - ParallelFor, AsyncTask๋กœ ๋””์ŠคํŒจ์น˜๋œ ์ž‘์—… ์ฒ˜๋ฆฌ
  - ์ฝ”์–ด ์ˆ˜๋งŒํผ ์ž๋™ ์ƒ์„ฑ

10.2 ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ / ๋ Œ๋” ์Šค๋ ˆ๋“œ ๋ถ„๋ฆฌ โ€” ์™œ ํ•„์š”ํ•œ๊ฐ€

1
2
3
4
5
6
7
8
9
10
[์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ]   60fps ๋ชฉํ‘œ โ†’ 16.6ms / ํ”„๋ ˆ์ž„
  Tick โ†’ Draw โ†’ Tick โ†’ Draw ...
  CPU์™€ GPU๊ฐ€ ์ง๋ ฌํ™”๋˜์–ด ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€

[๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ๋ชจ๋ธ]
  ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ:  Tick(1) โ†’ Tick(2) โ†’ Tick(3) ...
  ๋ Œ๋” ์Šค๋ ˆ๋“œ:           Draw(1) โ†’ Draw(2) ...   (1ํ”„๋ ˆ์ž„ ์ง€์—ฐ)
  GPU:                            GPU(1) โ†’ GPU(2) ...

  โ†’ ๊ฐ™์€ 16.6ms ์•ˆ์— ๋” ๋งŽ์€ ์ž‘์—…

โ†’ ๊ฒŒ์ž„ ์—”์ง„์ด IPC ๋ถ€๋‹ด์„ ์ ˆ๋Œ€ ๋ชป ๊ฒฌ๋””๋Š” ํ™˜๊ฒฝ์˜ ์ „ํ˜•. ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค์˜ ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณต์œ ํ•ด์•ผ๋งŒ 60fps๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

10.3 FRunnable / FRunnableThread โ€” ์›Œ์ปค ์Šค๋ ˆ๋“œ ๋งŒ๋“ค๊ธฐ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class FMyWorker : public FRunnable
{
public:
    virtual bool Init() override { return true; }
    virtual uint32 Run() override
    {
        while (!bStopped)
        {
            // ๋ฌด๊ฑฐ์šด ์ž‘์—… (๋„คํŠธ์›Œํฌ, ํŒŒ์ผ IO, ์—ฐ์‚ฐ)
        }
        return 0;
    }
    virtual void Stop() override { bStopped = true; }
private:
    std::atomic<bool> bStopped{false};
};

// ์‹œ์ž‘
FMyWorker* Worker = new FMyWorker();
FRunnableThread* Thread = FRunnableThread::Create(Worker, TEXT("MyWorker"));

โ†’ std::thread์˜ ์–ธ๋ฆฌ์–ผ ๋ฒ„์ „. ๋ฉ€ํ‹ฐ ํ”Œ๋žซํผ ์ถ”์ƒํ™”(WindowsยทLinuxยท์ฝ˜์†”) ์ œ๊ณต.

10.4 AsyncTask โ€” ์งง์€ ์ž‘์—… ํ’€์— ๋””์ŠคํŒจ์น˜

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "Async/AsyncWork.h"

AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, []()
{
    // ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์›Œ์ปค์—์„œ ์‹คํ–‰
    HeavyWork();

    // ๊ฒฐ๊ณผ๋ฅผ ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ๋กœ ๋‹ค์‹œ
    AsyncTask(ENamedThreads::GameThread, []()
    {
        UpdateUI();
    });
});

โ†’ โ€œ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฌด๊ฑฐ์šด ์ผ โ†’ ๋๋‚˜๋ฉด ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ์—์„œ UI ๊ฐฑ์‹ โ€ ํŒจํ„ด. UE์˜ ํ‘œ์ค€.

10.5 ParallelFor โ€” ๋ฐ์ดํ„ฐ ๋ณ‘๋ ฌ

1
2
3
4
5
6
7
#include "Async/ParallelFor.h"

ParallelFor(NumActors, [&](int32 Index)
{
    // Index 0..NumActors-1์„ ์›Œ์ปค ํ’€์ด ๋ถ„๋‹ด
    Actors[Index]->ProcessHeavy();
});

โ†’ for ๋ฃจํ”„๋ฅผ ์ž๋™ ๋ณ‘๋ ฌํ™”. ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœํ•ด๋„ ์›Œ์ปค ์Šค๋ ˆ๋“œ๊ฐ€ ๋ถ„๋‹ด.

10.6 FCriticalSection / FScopeLock โ€” RAII ๋ฝ (Community 7 ํšŒ๊ท€)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "HAL/CriticalSection.h"

class FMyData
{
public:
    void Add(int32 Value)
    {
        FScopeLock Lock(&CS);   // ์ƒ์„ฑ ์‹œ lock, ์†Œ๋ฉธ ์‹œ unlock
        Data.Add(Value);
    }
private:
    mutable FCriticalSection CS;
    TArray<int32> Data;
};

โ†’ std::lock_guard์˜ ์–ธ๋ฆฌ์–ผ ๋Œ€์‘. 9๋ฒˆ RAII์™€ 18๋ฒˆ Community 18(Mutex ๋ฝ)์˜ ํŒจํ„ด ๊ทธ๋Œ€๋กœ.

10.7 ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ ์ฒดํฌ ๋งคํฌ๋กœ

1
2
check(IsInGameThread());     // ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœ๋˜๋Š”์ง€ ๊ฒ€์ฆ
check(IsInRenderingThread()); // ๋ Œ๋” ์Šค๋ ˆ๋“œ์—์„œ ํ˜ธ์ถœ๋˜๋Š”์ง€ ๊ฒ€์ฆ

โ†’ UObjectยทAActor ์กฐ์ž‘ ์ฝ”๋“œ๋Š” ๋ณดํ†ต check(IsInGameThread())๋กœ ์‹œ์ž‘. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์•ˆ์ „ ์œ„๋ฐ˜ ๋””๋ฒ„๊น… ํ•ต์‹ฌ.

10.8 ์–ธ๋ฆฌ์–ผ โ†” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋Œ€์‘

std::Unreal
std::threadFRunnable + FRunnableThread
std::mutexFCriticalSection
std::lock_guardFScopeLock
std::atomic<T>TAtomic<T> ๋˜๋Š” ๊ทธ๋Œ€๋กœ std::atomic
std::async / std::futureAsyncTask / TFuture / TPromise
std::condition_variableFEvent (Trigger / Wait)
std::this_thread::sleep_forFPlatformProcess::Sleep

โ†’ ์–ธ๋ฆฌ์–ผ์€ ์ž์ฒด ์ถ”์ƒํ™” ์œ„์ฃผ์ง€๋งŒ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๊ฐ™์€ OS ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ.


11. ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์˜ˆ์ƒ ๊ฒฝ๋กœ

Q1. โ€œํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ์˜ ์ฐจ์ด๋ฅผ ํ•œ ๋ฌธ์žฅ์œผ๋กœ ์š”์•ฝํ•˜๋ฉด?โ€

ํ”„๋กœ์„ธ์Šค๋Š” ์ž์›์„ ์†Œ์œ ํ•˜๋Š” ๋‹จ์œ„, ์Šค๋ ˆ๋“œ๋Š” ๊ทธ ์ž์› ์œ„์—์„œ ์‹คํ–‰๋˜๋Š” ํ๋ฆ„์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค๋Š” ๋ฉ”๋ชจ๋ฆฌยทํ•ธ๋“คยท๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐ€์ง€๊ณ , ์Šค๋ ˆ๋“œ๋Š” ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค์˜ ์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™์„ ๊ณต์œ ํ•˜๋ฉด์„œ ์ž๊ธฐ ์Šคํƒ๊ณผ ๋ ˆ์ง€์Šคํ„ฐยทPC๋งŒ ๋”ฐ๋กœ ๊ฐ–์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์Šค๋ ˆ๋“œ ๊ฐ„ ํ†ต์‹ ์€ ๋น ๋ฅด์ง€๋งŒ ๋™๊ธฐํ™” ๋ฌธ์ œ๊ฐ€ ๋”ฐ๋ผ์˜ค๊ณ , ํ”„๋กœ์„ธ์Šค ๊ฐ„ ํ†ต์‹ ์€ ๊ฒฉ๋ฆฌ๊ฐ€ ์ข‹์ง€๋งŒ IPC ๋น„์šฉ์ด ๋“ญ๋‹ˆ๋‹ค.

Q2. โ€œ์Šค๋ ˆ๋“œ๋ผ๋ฆฌ ๋ฌด์—‡์„ ๊ณต์œ ํ•˜๊ณ  ๋ฌด์—‡์„ ๊ณต์œ ํ•˜์ง€ ์•Š๋‚˜์š”?โ€

๊ณต์œ : ์ฝ”๋“œ ์˜์—ญ, ์ „์—ญยทstatic ๋ฐ์ดํ„ฐ, ํž™, ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ, ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ์ „์ฒด. ๋…๋ฆฝ: ์Šคํƒ, ๋ ˆ์ง€์Šคํ„ฐ ์ปจํ…์ŠคํŠธ(PCยทSPยท๋ฒ”์šฉ ๋ ˆ์ง€์Šคํ„ฐ), TID, ์‹œ๊ทธ๋„ ๋งˆ์Šคํฌ, TLS(Thread Local Storage). ์—ฌ๊ธฐ์„œ ๊ฒฐ์ •์ ์ธ ๊ฑด ํž™์ด ๊ณต์œ ๋œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค โ€” new๋กœ ํ• ๋‹นํ•œ ๊ฐ์ฒด๋ฅผ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•จ๊ป˜ ๋ณด๊ธฐ ๋•Œ๋ฌธ์— mutex ๊ฐ™์€ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•ด์ง‘๋‹ˆ๋‹ค.

Q3. โ€œ์Šค๋ ˆ๋“œ์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์ด ํ”„๋กœ์„ธ์Šค๋ณด๋‹ค ์™œ ๋น ๋ฅธ๊ฐ€์š”?โ€

๊ฐ€์žฅ ํฐ ์ด์œ ๋Š” TLB์™€ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”์„ ๊ทธ๋Œ€๋กœ ๋‘๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค ์ „ํ™˜์€ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์ด ๋ฐ”๋€Œ๋‹ˆ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šค ๋ ˆ์ง€์Šคํ„ฐ(x86 CR3)๋ฅผ ๊ต์ฒดํ•˜๊ณ  TLB๋ฅผ ๋น„์›Œ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์งํ›„์˜ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์ด ๋ชจ๋‘ TLB miss๊ฐ€ ๋‚˜์„œ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ์›Œํฌ๋ฅผ ๋‹ค์‹œ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. L1ยทL2 ์บ์‹œ๋„ ์ฐจ๊ฐ€์›Œ์ง€์ฃ . ์Šค๋ ˆ๋“œ ์ „ํ™˜์€ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ์•ˆ์—์„œ ์ผ์–ด๋‚˜๋‹ˆ ์ด ๋ชจ๋“  ๊ณผ์ •์ด ์ƒ๋žต๋˜๊ณ  ๋ ˆ์ง€์Šคํ„ฐ๋งŒ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ผ๋ฐ˜์ ์œผ๋กœ 5~10๋ฐฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.

Q4. โ€œ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๋ณ€์ˆ˜์— ๋™์‹œ์— ์ ‘๊ทผํ•˜๋ฉด ๋ฌด์Šจ ์ผ์ด ์ƒ๊ธฐ๋‚˜์š”?โ€

race condition์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด counter++๋„ ์‚ฌ์‹ค์€ loadยทaddยทstore ์„ธ ๋‹จ๊ณ„๋ผ, ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ์ธํ„ฐ๋ฆฌ๋น™๋˜๋ฉด ํ•œ ์ชฝ ๊ฐฑ์‹ ์ด ์‚ฌ๋ผ์ง€๋Š” lost update๊ฐ€ ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๊ฐ€ ๋น„๊ฒฐ์ •์ ์ด๊ณ  ๋””๋ฒ„๊น…๋„ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐ์ฑ…์€ ์ž„๊ณ„ ๊ตฌ์—ญ(critical section)์„ mutex๋กœ ๋ณดํ˜ธํ•˜๊ฑฐ๋‚˜, ๋‹จ์ˆœํ•œ ์นด์šดํ„ฐ๋ผ๋ฉด std::atomic์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. C++์—์„  std::lock_guard๋‚˜ std::scoped_lock ๊ฐ™์€ RAII ๋ฝ์„ ์จ์„œ ์˜ˆ์™ธ ์•ˆ์ „์„ฑ๋„ ๊ฐ™์ด ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

Q5. โ€œdeadlock์ด ๋ญ”๊ฐ€์š”? 4๊ฐ€์ง€ ์กฐ๊ฑด ์•Œ๊ณ  ๊ณ„์‹ ๊ฐ€์š”?โ€

deadlock์€ ๋‘ ๊ฐœ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์„œ๋กœ์˜ ์ž์›์„ ๋ฌดํ•œํžˆ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ์˜์›ํžˆ ๋ฉˆ์ถ”๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค. Coffman conditions๋ผ ๋ถ€๋ฅด๋Š” 4๊ฐ€์ง€ ์กฐ๊ฑด์ด ๋™์‹œ์— ๋งŒ์กฑ๋ผ์•ผ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค โ€” โ‘  ์ƒํ˜ธ ๋ฐฐ์ œ(์ž์›์„ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜๋งŒ), โ‘ก ์ ์œ ์™€ ๋Œ€๊ธฐ(์ž์›์„ ๋“  ์ฑ„ ๋‹ค๋ฅธ ์ž์› ๋Œ€๊ธฐ), โ‘ข ๋น„์„ ์ (๊ฐ•์ œ๋กœ ๋นผ์•—์„ ์ˆ˜ ์—†์Œ), โ‘ฃ ์ˆœํ™˜ ๋Œ€๊ธฐ(์›ํ˜•์œผ๋กœ ๊ธฐ๋‹ค๋ฆผ). ํšŒํ”ผ ๋ฐฉ๋ฒ•์€ ๋ฝ ์ˆœ์„œ๋ฅผ ์ •ํ•ด์„œ ์ˆœํ™˜ ๋Œ€๊ธฐ๋ฅผ ๊นจ๊ฑฐ๋‚˜, C++17์˜ std::scoped_lock์œผ๋กœ ์—ฌ๋Ÿฌ mutex๋ฅผ ๋™์‹œ์— ์•ˆ์ „ํ•˜๊ฒŒ ์žก๊ฑฐ๋‚˜, try_lock + back-off๋กœ ์ ์œ ์™€ ๋Œ€๊ธฐ๋ฅผ ๊นจ๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

Q6. โ€œChrome์€ ์™œ ํƒญ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค๋ฅผ ์“ฐ๋‚˜์š”?โ€

์„ธ ๊ฐ€์ง€ ์ด์œ ์ž…๋‹ˆ๋‹ค. ์ฒซ์งธ ๋ณด์•ˆ โ€” ์•…์„ฑ ์‚ฌ์ดํŠธ๊ฐ€ ๋‹ค๋ฅธ ํƒญ์˜ ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๋„๋ก OS ๋ ˆ๋ฒจ ๊ฒฉ๋ฆฌ(sandbox)๋ฅผ ํ™œ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‘˜์งธ ์•ˆ์ •์„ฑ โ€” ํ•œ ํƒญ์ด ํฌ๋ž˜์‹œํ•ด๋„ ๊ทธ ํ”„๋กœ์„ธ์Šค๋งŒ ์ฃฝ์–ด์„œ ๋‚˜๋จธ์ง€ ํƒญ์€ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์…‹์งธ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๊ฒฉ๋ฆฌ โ€” ํƒญ์„ ๋‹ซ์œผ๋ฉด ๊ทธ ํ”„๋กœ์„ธ์Šค ๋ฉ”๋ชจ๋ฆฌ๋ฅผ OS๊ฐ€ ํ†ต์งธ๋กœ ํšŒ์ˆ˜ํ•˜๋ฏ€๋กœ ๋ˆ„์ˆ˜๊ฐ€ ๋ˆ„์ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€๊ฐ€๋Š” ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰๊ณผ IPC ๋น„์šฉ์ธ๋ฐ, ๋ณด์•ˆ๊ณผ ์•ˆ์ •์„ฑ์ด ๊ทธ๋งŒํผ ์ค‘์š”ํ•ด์„œ ๋ฐ›์•„๋“ค์ด๋Š” ํŠธ๋ ˆ์ด๋“œ์˜คํ”„์ž…๋‹ˆ๋‹ค.

Q7. โ€œ๊ทธ๋Ÿผ ๊ฒŒ์ž„ ์—”์ง„์€ ์™œ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ์“ฐ๋‚˜์š”?โ€

๋งค ํ”„๋ ˆ์ž„ 16.6ms ์•ˆ์— ๋ชจ๋“  ์ผ์„ ๋๋‚ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(60fps ๊ธฐ์ค€). ํ”„๋กœ์„ธ์Šค ๊ฐ„ IPC ๋น„์šฉ์€ ๋งˆ์ดํฌ๋กœ์ดˆ ๋‹จ์œ„๋กœ ๋ˆ„์ ๋˜๊ณ  ๊ฒŒ์ž„ ๊ฐ์ฒด ์ˆ˜๋งŒ ๊ฐœ๋ฅผ ๋งค ํ”„๋ ˆ์ž„ ๋™๊ธฐํ™”ํ•˜๋ ค๋ฉด ๊ฒฌ๋”œ ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ์•ˆ์—์„œ ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ(๋กœ์ง)์™€ ๋ Œ๋” ์Šค๋ ˆ๋“œ(GPU ๋ช…๋ น)๋ฅผ ๋ถ„๋ฆฌํ•ด ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋กœ ํ†ต์‹ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  race condition ์œ„ํ—˜์„ ์•ˆ๊ณ  mutexยทatomicยทlock-free ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ๋ณดํ˜ธํ•ฉ๋‹ˆ๋‹ค. ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ํฌ๋ž˜์‹œํ•˜๋ฉด ๊ฒŒ์ž„ ์ „์ฒด๊ฐ€ ์ฃฝ๋Š”๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์ง€๋งŒ, 60fps๋ผ๋Š” hard real-time ์š”๊ตฌ๊ฐ€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.

Q8. โ€œ1:1 / N:1 / M:N ๋ชจ๋ธ์ด ๋ญ”๊ฐ€์š”?โ€

์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ์™€ ์ปค๋„ ์Šค๋ ˆ๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ๋งคํ•‘ํ•˜๋А๋ƒ์˜ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค. 1:1์€ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ ํ•˜๋‚˜์— ์ปค๋„ ์Šค๋ ˆ๋“œ ํ•˜๋‚˜๋ฅผ 1:1๋กœ ๋Œ€์‘์‹œํ‚ค๋Š” ๋ฐฉ์‹์œผ๋กœ, Linux pthreadยทWindows Threadยทstd::thread๊ฐ€ ๋‹ค 1:1์ž…๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ ์ฝœ ์ฐจ๋‹จ ์‹œ ๊ทธ ์Šค๋ ˆ๋“œ๋งŒ ์˜ํ–ฅ์„ ๋ฐ›๊ณ  ๋ฉ€ํ‹ฐ ์ฝ”์–ด ํ™œ์šฉ๋„ ์ž์—ฐ์Šค๋Ÿฝ์ง€๋งŒ ์ƒ์„ฑ ๋น„์šฉ์ด ํฝ๋‹ˆ๋‹ค. N:1์€ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์ปค๋„ ์Šค๋ ˆ๋“œ ํ•˜๋‚˜์— ๋งคํ•‘ํ•˜๋Š”๋ฐ, ๋งค์šฐ ๊ฐ€๋ณ์ง€๋งŒ ํ•œ ์Šค๋ ˆ๋“œ์˜ ์‹œ์Šคํ…œ ์ฝœ ์ฐจ๋‹จ์œผ๋กœ ์ „๋ถ€ ๋ฉˆ์ถ”๊ณ  ๋ฉ€ํ‹ฐ ์ฝ”์–ด๋ฅผ ๋ชป ์”๋‹ˆ๋‹ค โ€” ๊ฑฐ์˜ ์•ˆ ์“ฐ์ž…๋‹ˆ๋‹ค. M:N์€ ๋‘˜์˜ ์ ˆ์ถฉ์œผ๋กœ Go ๊ณ ๋ฃจํ‹ด์ด๋‚˜ Java Loom virtual thread๊ฐ€ M:N์ž…๋‹ˆ๋‹ค. ์ˆ˜๋งŒ ๊ฐœ ์‚ฌ์šฉ์ž ์Šค๋ ˆ๋“œ๋ฅผ ์ ์€ ์ˆ˜์˜ ์ปค๋„ ์Šค๋ ˆ๋“œ ์œ„์—์„œ ๋Œ๋ฆฌ๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.

Q9. โ€œshared_ptr์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ์—์„œ ์•ˆ์ „ํ•œ๊ฐ€์š”?โ€

์ฐธ์กฐ ์นด์šดํ„ฐ ์ž์ฒด๋Š” atomic์ด๋ผ ์•ˆ์ „ํ•˜์ง€๋งŒ, shared_ptr์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋™์‹œ ์ ‘๊ทผ์€ ์•ˆ์ „ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 11๋ฒˆ์—์„œ ์ •๋ฆฌํ•œ ๊ทธ๋Œ€๋กœ โ€” ์ œ์–ด ๋ธ”๋ก์˜ reference count๋Š” std::atomic์œผ๋กœ ์ฆ๊ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ shared_ptr์„ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜ ์†Œ๋ฉธ์‹œ์ผœ๋„ ์นด์šดํ„ฐ๋Š” ์ •ํ™•ํ•˜๊ฒŒ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ shared_ptr์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹ค์ œ ๊ฐ์ฒด ์ž์ฒด์— ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์“ฐ๋ฉด race condition์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ์ฒด ์ ‘๊ทผ์€ ๋ณ„๋„๋กœ mutex๋‚˜ atomic์œผ๋กœ ๋ณดํ˜ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. atomic_load/store๊ฐ€ shared_ptr ์ž์ฒด์—๋„ ์žˆ์–ด์„œ ๊ฐ™์€ ๋ณ€์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋กœ ๊ฐˆ์•„์น˜์šฐ๋Š” ํŒจํ„ด์—” ๊ทธ๊ฑธ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Q10. โ€œSTL ์ปจํ…Œ์ด๋„ˆ๋Š” thread-safeํ•œ๊ฐ€์š”?โ€

๊ฐœ๋ณ„ ์ปจํ…Œ์ด๋„ˆ๋Š” thread-safeํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ‘œ์ค€์˜ ๋ณด์žฅ์€ โ€œํ•œ ์ปจํ…Œ์ด๋„ˆ์˜ const ๋ฉค๋ฒ„ ํ•จ์ˆ˜๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ํ˜ธ์ถœํ•ด๋„ ์•ˆ์ „โ€œ๊ณผ โ€œ์„œ๋กœ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ ๊ฐ์ฒด๋Š” ๊ฐ์ž ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž์œ ๋กญ๊ฒŒ ์จ๋„ ์•ˆ์ „โ€ ์ •๋„์ž…๋‹ˆ๋‹ค. ๊ฐ™์€ ์ปจํ…Œ์ด๋„ˆ์— ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— push_back์„ ํ•˜๋ฉด race condition์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ 16๋ฒˆ์—์„œ ์ •๋ฆฌํ•œ ๋Œ€๋กœ ๋ณดํ˜ธ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—” ์™ธ๋ถ€์—์„œ mutex๋กœ ๊ฐ์‹ธ๊ฑฐ๋‚˜, ๋ฝ-ํ”„๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด concurrent_queue ๊ฐ™์€ ๋™์‹œ์„ฑ ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋กœ ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์–ธ๋ฆฌ์–ผ์€ TQueue<T, EQueueMode::Mpsc> ๊ฐ™์€ ๋ฝ-ํ”„๋ฆฌ ํ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Q11. โ€œfork()๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋‚˜์š”?โ€

fork()๋Š” ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณต์ œํ•ด์„œ ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ์‹œ์Šคํ…œ ์ฝœ์ž…๋‹ˆ๋‹ค. ์ž์‹์€ ๋ถ€๋ชจ์™€ ๊ฑฐ์˜ ๋™์ผํ•œ ๋ฉ”๋ชจ๋ฆฌ ์ƒํƒœ๋กœ ์‹œ์ž‘ํ•˜์ง€๋งŒ, ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์ด ๋ณ„๊ฐœ์ž…๋‹ˆ๋‹ค. ํ•ต์‹ฌ ์ตœ์ ํ™”๊ฐ€ Copy-On-Write(COW)์ž…๋‹ˆ๋‹ค โ€” ์ฒ˜์Œ์—” ๋ถ€๋ชจ์™€ ์ž์‹์ด ๊ฐ™์€ ๋ฌผ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ๊ณต์œ ํ•˜๋‹ค๊ฐ€, ์–ด๋А ์ชฝ์ด๋“  ๊ทธ ํŽ˜์ด์ง€์— ์“ฐ๊ธฐ๋ฅผ ์‹œ๋„ํ•˜๋ฉด ๊ทธ ์‹œ์ ์— OS๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ fork ์งํ›„์—” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฑฐ์˜ ์•ˆ ์“ฐ๊ณ  ๋น ๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”ยทPCBยทํ•ธ๋“ค ํ…Œ์ด๋ธ” ๋ณต์‚ฌ ๊ฐ™์€ ๊ณ ์ • ๋น„์šฉ์ด ์žˆ์–ด์„œ ์Šค๋ ˆ๋“œ ์ƒ์„ฑ๋ณด๋‹ค๋Š” ๋น„์Œ‰๋‹ˆ๋‹ค. Postgresยท์ „ํ†ต์  Apache๊ฐ€ fork ๋ชจ๋ธ์„ ์“ฐ๋Š” ์ด์œ ๊ฐ€ ๊ฒฉ๋ฆฌ์™€ ์•ˆ์ •์„ฑ์ด๊ณ , fork ๋น„์šฉ์€ connection pooling์œผ๋กœ ๊ฐ์ถฅ๋‹ˆ๋‹ค.

Q12. โ€œFRunnable๊ณผ std::thread์˜ ์ฐจ์ด๋Š” ๋ญ”๊ฐ€์š”?โ€

๋ณธ์งˆ์€ ๊ฐ™์ง€๋งŒ ์ถ”์ƒํ™” ์ˆ˜์ค€์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค. std::thread๋Š” OS ์Šค๋ ˆ๋“œ๋ฅผ ์ง์ ‘ ๋ž˜ํ•‘ํ•œ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ณ , FRunnable์€ ์–ธ๋ฆฌ์–ผ์ด ๊ทธ ์œ„์— ๋งŒ๋“  ์›Œ์ปค ์Šค๋ ˆ๋“œ ์ถ”์ƒํ™”์ž…๋‹ˆ๋‹ค. ์ฐจ์ด๋Š” โ‘  ๋ฉ€ํ‹ฐ ํ”Œ๋žซํผ โ€” FRunnable + FRunnableThread::Create๋Š” WindowsยทLinuxยท์ฝ˜์†” ๊ตฌ๋ถ„ ์—†์ด ๋™์ž‘, โ‘ก ๋ผ์ดํ”„์‚ฌ์ดํด ํ›… โ€” Init(), Run(), Stop(), Exit() ๊ฐ€ ํ‘œ์ค€ํ™”๋ผ ์žˆ์–ด์„œ cleanup ํŒจํ„ด์ด ์ผ๊ด€๋จ, โ‘ข UE์˜ FCriticalSectionยทFEventยทFScopeLock๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ฒฐํ•ฉ. ์งง์€ ์ž‘์—…์ด๋ผ๋ฉด FRunnable ์ง์ ‘ ๋งŒ๋“ค๊ธฐ๋ณด๋‹ค AsyncTask๋‚˜ ParallelFor๋ฅผ ์“ฐ๋Š” ๊ฒŒ ๋” ํ”ํ•ฉ๋‹ˆ๋‹ค.


Q13. โ€œ๋ฐ˜๋ณต์ž(iterator)์˜ ๋ฌดํšจํ™”๋Š” ์™œ ์ผ์–ด๋‚˜๊ณ  ์–ด๋–ป๊ฒŒ ๋ฐฉ์ง€ํ•˜๋‚˜์š”?โ€

๋ฐ˜๋ณต์ž ๋ฌดํšจํ™”๋Š” ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ๊ฐ€ ๋ฐ”๋€Œ์–ด ๊ธฐ์กด iterator๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋˜ ์œ„์น˜๊ฐ€ ๋” ์ด์ƒ ์œ ํšจํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋Š” ํ˜„์ƒ์ž…๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ ์ข…๋ฅ˜๋งˆ๋‹ค ์ •์ฑ…์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

std::vector โ€” ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ๋ผ ๊ฐ€์žฅ ์ทจ์•ฝํ•ฉ๋‹ˆ๋‹ค. push_back์ด capacity๋ฅผ ์ดˆ๊ณผํ•ด ์žฌํ• ๋‹น์ด ์ผ์–ด๋‚˜๋ฉด ๋ชจ๋“  iteratorยทํฌ์ธํ„ฐยท์ฐธ์กฐ๊ฐ€ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค. ์ค‘๊ฐ„ erase/insert๋„ ๊ทธ ์œ„์น˜ ์ดํ›„์˜ ๋ชจ๋“  iterator๊ฐ€ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค.

std::list โ€” ๋…ธ๋“œ ๊ธฐ๋ฐ˜์ด๋ผ ์•ˆ์ „ํ•œ ํŽธ์ž…๋‹ˆ๋‹ค. eraseํ•œ ๋…ธ๋“œ์˜ iterator๋งŒ ๋ฌดํšจํ™”๋˜๊ณ , ๋‹ค๋ฅธ ๋…ธ๋“œ์˜ iterator๋Š” ๊ทธ๋Œ€๋กœ์ž…๋‹ˆ๋‹ค.

std::map / std::set (RB-tree) โ€” eraseํ•œ ๋…ธ๋“œ์˜ iterator๋งŒ ๋ฌดํšจํ™”. ํŠธ๋ฆฌ ํšŒ์ „์ด ์ผ์–ด๋‚˜๋„ ๋‹ค๋ฅธ ๋…ธ๋“œ๋Š” ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

std::unordered_map / std::unordered_set โ€” rehash(load factor ์ดˆ๊ณผ)๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ๋ชจ๋“  iterator๊ฐ€ ๋ฌดํšจํ™”๋ฉ๋‹ˆ๋‹ค. ๋‹จ ํฌ์ธํ„ฐ/์ฐธ์กฐ๋Š” ๊ทธ๋Œ€๋กœ ์œ ์ง€๋œ๋‹ค๋Š” ์ ์ด vector์™€ ๋‹ค๋ฅธ ๋ฏธ๋ฌ˜ํ•œ ์ฐจ์ด์ž…๋‹ˆ๋‹ค.

๋ฐฉ์ง€ ๋ฐฉ๋ฒ•์€ โ‘  reserve()๋กœ capacity ๋ฏธ๋ฆฌ ํ™•๋ณด(vector), โ‘ก erase์˜ ๋ฆฌํ„ด๊ฐ’(๋‹ค์Œ ์œ ํšจ iterator)์„ ๋ฐ˜๋“œ์‹œ ๋ฐ›๊ธฐ โ€” it = v.erase(it), โ‘ข โ€œiterator ๋ณด๊ด€ ์ค‘์—๋Š” ์ปจํ…Œ์ด๋„ˆ ์ˆ˜์ • ๊ธˆ์ง€โ€ ์›์น™, โ‘ฃ vector์—์„  ์ธ๋ฑ์Šค ๊ธฐ๋ฐ˜ ์ ‘๊ทผ์œผ๋กœ ๋Œ€์ฒด ๊ฒ€ํ† . ์ž์„ธํ•œ ์ปจํ…Œ์ด๋„ˆ๋ณ„ ํ‘œ๋Š” 13๋ฒˆ(vector vs list), 14๋ฒˆ(map), 16๋ฒˆ(STL ์ปจํ…Œ์ด๋„ˆ ํ†ตํ•ฉ)์— ์ •๋ฆฌ๋ผ ์žˆ์Šต๋‹ˆ๋‹ค.

Q14. โ€œ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ(stack overflow)๋Š” ์–ธ์ œ ๋ฐœ์ƒํ•˜๋‚˜์š”?โ€

์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ๋Š” ์Šค๋ ˆ๋“œ์˜ ์Šคํƒ ์˜์—ญ์ด ํ•œ๊ณ„๋ฅผ ์ดˆ๊ณผํ•ด ๋” ์ด์ƒ ํ•จ์ˆ˜ ํ˜ธ์ถœ ํ”„๋ ˆ์ž„์„ ์Œ“์„ ์ˆ˜ ์—†์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.

์ฃผ์š” ์›์ธ ์„ธ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค โ€” ์ฒซ์งธ ๋ฌดํ•œ ์žฌ๊ท€ ๋˜๋Š” ์ข…๋ฃŒ ์กฐ๊ฑด์ด ์—†๋Š” ์žฌ๊ท€, ๋‘˜์งธ ๋„ˆ๋ฌด ๊นŠ์€ ์žฌ๊ท€(ํŠธ๋ฆฌ DFSยทnaive ํ”ผ๋ณด๋‚˜์น˜ ๋“ฑ), ์…‹์งธ ๊ฑฐ๋Œ€ํ•œ ์ง€์—ญ ๋ณ€์ˆ˜(int arr[1000000] ๊ฐ™์€ ๋Œ€์šฉ๋Ÿ‰ ๋ฐฐ์—ด์„ ์Šคํƒ์— ์žก๋Š” ๊ฒฝ์šฐ).

์Šคํƒ ํฌ๊ธฐ๋Š” OSยทํ”Œ๋žซํผ๋ณ„๋กœ ๋‹ค๋ฆ…๋‹ˆ๋‹ค โ€” Windows ๋ฉ”์ธ ์Šค๋ ˆ๋“œ ๊ธฐ๋ณธ 1MB, Linux ๊ธฐ๋ณธ 8MB(ulimit -s), ์›Œ์ปค ์Šค๋ ˆ๋“œ๋Š” ๋ณดํ†ต ๋” ์ž‘์Šต๋‹ˆ๋‹ค(๋ณดํ†ต 1~2MB). ์–ธ๋ฆฌ์–ผ์˜ FRunnableThread::Create๋„ ๊ธฐ๋ณธ 0์ด๋ฉด OS ๊ธฐ๋ณธ๊ฐ’์„ ์“ฐ์ง€๋งŒ ๋ช…์‹œ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋ฐœ์ƒ ์‹œ Linux์—์„  SIGSEGV๋กœ ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ, Windows์—์„  0xC00000FD STATUS_STACK_OVERFLOW ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฑด 19๋ฒˆ์—์„œ ์ •๋ฆฌํ•œ 4์˜์—ญ ๋ชจ๋ธ์˜ Stack ์˜์—ญ ํ•œ๊ณ„๊ฐ€ ๊ทธ๋Œ€๋กœ ๋“œ๋Ÿฌ๋‚˜๋Š” ์‚ฌ๋ก€๊ณ , ๊ทธ๋ž˜์„œ ํฐ ๋ฐ์ดํ„ฐ๋Š” ์Šคํƒ ๋Œ€์‹  ํž™(new/std::vector)์— ์žก๋Š” ๊ฒŒ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

Q15. โ€œ์žฌ๊ท€๊ฐ€ ์–ด๋–ป๊ฒŒ ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ๋ฅผ ์ผ์œผํ‚ค๋‚˜์š”? ํ”ผ๋ณด๋‚˜์น˜๋ฅผ ์˜ˆ๋กœ ๋“ค๋ฉด?โ€

์žฌ๊ท€(recursion)๋Š” ํ•จ์ˆ˜๊ฐ€ ์ž๊ธฐ ์ž์‹ ์„ ํ˜ธ์ถœํ•˜๋Š” ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ํ˜ธ์ถœ์ด ํ•œ ๋ฒˆ ์ผ์–ด๋‚  ๋•Œ๋งˆ๋‹ค ์Šคํƒ์— ์ƒˆ ํ•จ์ˆ˜ ํ”„๋ ˆ์ž„์ด push๋ฉ๋‹ˆ๋‹ค. ์ข…๋ฃŒ ์กฐ๊ฑด(base case)์ด ์—†๊ฑฐ๋‚˜ ๊นŠ์ด๊ฐ€ ๋„ˆ๋ฌด ํฌ๋ฉด ์Šคํƒ์„ ๋‹ค ์ฑ„์›Œ ์˜ค๋ฒ„ํ”Œ๋กœ๊ฐ€ ๋‚ฉ๋‹ˆ๋‹ค.

์ „ํ˜•์ ์ธ ์˜ˆ์‹œ๊ฐ€ naive ํ”ผ๋ณด๋‚˜์น˜์ž…๋‹ˆ๋‹ค.

1
2
3
4
int fib(int n) {
    if (n < 2) return n;          // ์ข…๋ฃŒ ์กฐ๊ฑด
    return fib(n - 1) + fib(n - 2); // ์ž๊ธฐ ์ž์‹  ๋‘ ๋ฒˆ ํ˜ธ์ถœ
}

fib(40) ์ •๋„๋งŒ ํ˜ธ์ถœํ•ด๋„ ํ•จ์ˆ˜ ํ˜ธ์ถœ ํŠธ๋ฆฌ๊ฐ€ ์•ฝ 10์–ต ๋ฒˆ ํŽผ์ณ์ง€๋ฉด์„œ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ O(2^n)์ด ๋ฉ๋‹ˆ๋‹ค. ์Šคํƒ ๊นŠ์ด๋Š” ์ตœ๋Œ€ n๊นŒ์ง€ ๊ฐ€๋Š”๋ฐ, ๊ฐ™์€ ๋ถ€๋ถ„ ๋ฌธ์ œ๋ฅผ ๋ฐ˜๋ณต ๊ณ„์‚ฐํ•˜๋Š” ๊ฒŒ ๋” ํฐ ๋ฌธ์ œ์ฃ .

๋งŒ์•ฝ ์ข…๋ฃŒ ์กฐ๊ฑด์ด ๋น ์ง€๋ฉด(if (n < 2) return n; ์ œ๊ฑฐ), fib(5) โ†’ fib(4) โ†’ fib(3) โ†’ ... ๋กœ ์Œ์ˆ˜๊นŒ์ง€ ๋ฌดํ•œํžˆ ๋‚ด๋ ค๊ฐ€์„œ ์Šคํƒ์„ ๊ฐ€๋“ ์ฑ„์šฐ๊ณ  ์ฃฝ์Šต๋‹ˆ๋‹ค โ€” ์ด๊ฒŒ โ€œ์ž๊ธฐ๊ฐ€ ์ž๊ธฐ๋ฅผ ํ˜ธ์ถœํ•˜๋Š”๋ฐ ๋ฉˆ์ถœ ์ค„ ๋ชจ๋ฅด๋Š”โ€ ๋ฌดํ•œ ์žฌ๊ท€์ž…๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์ฑ…์€ โ‘  ๋ฉ”๋ชจ์ด์ œ์ด์…˜ / DP โ€” ๊ฐ™์€ ๊ฐ’์€ ํ•œ ๋ฒˆ๋งŒ ๊ณ„์‚ฐํ•ด ์บ์‹ฑ(O(n)์œผ๋กœ ๋‹จ์ถ•), โ‘ก ๋ฐ˜๋ณต๋ฌธ ๋ณ€ํ™˜ โ€” for ๋ฃจํ”„๋กœ ํ’€๋ฉด ์Šคํƒ ํ•œ ํ”„๋ ˆ์ž„๋งŒ ์‚ฌ์šฉ, โ‘ข tail call optimization(TCO) โ€” ๋งˆ์ง€๋ง‰์— ์ž๊ธฐ ํ˜ธ์ถœ๋งŒ ๋‚จ๊ธฐ๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ ํ”„๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ C++ ํ‘œ์ค€์—์„  ๋ณด์žฅํ•˜์ง€ ์•Š์Œ(GCC/Clang ์ผ๋ถ€ ์ตœ์ ํ™”). ์•ˆ์ „ํ•˜๊ฒŒ ์“ฐ๋ ค๋ฉด ๋ฐ˜๋ณต๋ฌธ์ด๋‚˜ ๋ช…์‹œ์  ์Šคํƒ ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ํ’€์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Q16. โ€œrace condition์„ ์ •ํ™•ํžˆ ์ •์˜ํ•˜๋ฉด? mutex์™€ spin lock์˜ ์ฐจ์ด๋Š”?โ€

Race condition์€ ๋‘˜ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ  ๋ฐ์ดํ„ฐ์— ๋™์‹œ ์ ‘๊ทผํ•˜๋ฉด์„œ ์ ์–ด๋„ ํ•˜๋‚˜๊ฐ€ ์“ฐ๊ธฐ๋ฅผ ์ˆ˜ํ–‰ํ•  ๋•Œ, ์‹คํ–‰ ์ˆœ์„œ(์ธํ„ฐ๋ฆฌ๋น™)์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ€ ๋น„๊ฒฐ์ •์ ์œผ๋กœ ๋‹ฌ๋ผ์ง€๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค. counter++ ํ•œ ์ค„๋„ ์‚ฌ์‹ค์€ loadยทaddยทstore 3๋‹จ๊ณ„๋ผ ๋‘ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ผ์–ด๋“ค๋ฉด ๊ฐฑ์‹  ์†์‹ค์ด ์ผ์–ด๋‚˜๋Š” ๊ฒŒ ๋Œ€ํ‘œ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ์˜ ํ•ต์‹ฌ์€ ์ž„๊ณ„ ๊ตฌ์—ญ(critical section)์„ ํ•œ ๋ฒˆ์— ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ์‹คํ–‰ํ•˜๋„๋ก ๋ณดํ˜ธํ•˜๋Š” ๊ฒƒ์ด๊ณ , ๊ทธ ๋„๊ตฌ๊ฐ€ mutex(์ƒํ˜ธ ๋ฐฐ์ œ ๋ฝ)์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ mutex์—๋„ ๋‘ ๊ฐ€์ง€ ํฐ ๋ถ€๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

std::mutex (sleeping mutex) โ€” ๋ฝ์„ ๋ชป ์žก์œผ๋ฉด OS๊ฐ€ ๊ทธ ์Šค๋ ˆ๋“œ๋ฅผ ๋ธ”๋ก ์ƒํƒœ๋กœ ์ „ํ™˜ํ•˜๊ณ  ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์„ ์ผ์œผ์ผœ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— CPU๋ฅผ ๋„˜๊น๋‹ˆ๋‹ค. ๋ฝ์ด ํ’€๋ฆฌ๋ฉด OS๊ฐ€ ๊นจ์›Œ์ค๋‹ˆ๋‹ค. ์ž„๊ณ„ ๊ตฌ์—ญ์ด ๊ธธ๊ฑฐ๋‚˜(์ˆ˜ ฮผs ์ด์ƒ) ๋ฝ ๊ฒฝํ•ฉ์ด ์ ์€ ๊ฒฝ์šฐ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ์ด 1~10ฮผs ๋“ค์ง€๋งŒ ๊ทธ ์‹œ๊ฐ„ ๋™์•ˆ CPU๋ฅผ ๋‹ค๋ฅธ ์ผ์— ์“ธ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒŒ ์ด๋“์ด์ฃ .

spin lock (์Šคํ•€๋ฝ) โ€” ๋ฝ์„ ๋ชป ์žก์œผ๋ฉด CPU๋ฅผ ๋น™๋น™ ๋Œ๋ฉด์„œ(busy-wait) ๋ฝ์ด ํ’€๋ฆฌ๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์ด ์—†์œผ๋‹ˆ ๋ฝ์ด ํ’€๋ฆฌ๋Š” ์ฆ‰์‹œ ์ง„์ž…ํ•ฉ๋‹ˆ๋‹ค. ๋‹จ, CPU๋ฅผ ๊ทธ๋™์•ˆ ๋‚ญ๋น„ํ•ฉ๋‹ˆ๋‹ค. ์ž„๊ณ„ ๊ตฌ์—ญ์ด ๋งค์šฐ ์งง๊ณ (์ˆ˜์‹ญ ns~์ˆ˜ ฮผs) ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ™˜๊ฒฝ์ผ ๋•Œ ์ด๋“์ž…๋‹ˆ๋‹ค โ€” ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ๋ณด๋‹ค ์ž„๊ณ„ ๊ตฌ์—ญ์ด ์งง์œผ๋ฉด spin lock์ด ๋น ๋ฆ…๋‹ˆ๋‹ค. ๋‹จ์ผ ์ฝ”์–ด์—์„  ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฝ์„ ํ’€ ๊ธฐํšŒ ์ž์ฒด๊ฐ€ ์—†์–ด์„œ ์ ˆ๋Œ€ ์“ฐ๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

C++์—์„  std::mutex๋Š” ํ‘œ์ค€์ด์ง€๋งŒ spin lock์€ ํ‘œ์ค€์— ์—†๊ณ  std::atomic_flag::test_and_set์œผ๋กœ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ OS API๋ฅผ ์”๋‹ˆ๋‹ค. ์–ธ๋ฆฌ์–ผ์€ FCriticalSection(sleeping)๊ณผ FSpinLock(์Šคํ•€)์„ ๋‘˜ ๋‹ค ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ปค๋„ ์ฝ”๋“œ์—์„  ์ธํ„ฐ๋ŸฝํŠธ ํ•ธ๋“ค๋Ÿฌ์ฒ˜๋Ÿผ sleepํ•  ์ˆ˜ ์—†๋Š” ์ปจํ…์ŠคํŠธ๊ฐ€ ์žˆ์–ด์„œ spin lock์ด ํ•„์ˆ˜์ธ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

Q17. โ€œIPC๊ฐ€ ์ •ํ™•ํžˆ ๋ฌด์—‡์ธ๊ฐ€์š”?โ€

IPC(Inter-Process Communication)๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ฒฉ๋ฆฌ๋œ ๋‘ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๊ธฐ ์œ„ํ•œ OS ์ฐจ์›์˜ ๋ช…์‹œ์  ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์Šค๋Š” ๊ฐ์ž ๋…๋ฆฝ๋œ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๊ฐ€์ง€๋‹ˆ ๊ทธ๋ƒฅ ๋ณ€์ˆ˜๋กœ๋Š” ํ†ต์‹ ์ด ์•ˆ ๋˜๊ณ , OS๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ฑ„๋„์„ ๊ฑฐ์ณ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์š” ์ข…๋ฅ˜๋Š” ํŒŒ์ดํ”„(pipe), ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ(shared memory), ๋ฉ”์‹œ์ง€ ํ(message queue), ์†Œ์ผ“(socket), ์‹œ๊ทธ๋„(signal), mmap(ํŒŒ์ผ ๋งคํ•‘)์ž…๋‹ˆ๋‹ค. ์†๋„์™€ ๊ฒฉ๋ฆฌ๋„๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค โ€” ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๊ฐ€์žฅ ๋น ๋ฆ…๋‹ˆ๋‹ค(๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ์†๋„ ๊ทธ๋Œ€๋กœ), ๋‘ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ๊ฐ™์€ ๋ฌผ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ์ž๊ธฐ ๊ฐ€์ƒ ๊ณต๊ฐ„์— ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ์‹์ด๋ผ ํ•œ ๋ฒˆ ์„ค์ •ํ•˜๋ฉด ์ถ”๊ฐ€ ๋น„์šฉ์ด ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ์†Œ์ผ“์ด ๊ฐ€์žฅ ๋А๋ฆฌ์ง€๋งŒ(ํŠนํžˆ TCP๋Š” ์ปค๋„์„ ๊ฑฐ์น˜๋‹ˆ ์ˆ˜์‹ญ ฮผs ๋‹จ์œ„) ๋‹ค๋ฅธ ๋จธ์‹ ๊ณผ๋„ ํ†ต์‹  ๊ฐ€๋Šฅํ•œ ์œ ์—ฐ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ์€ IPC๊ฐ€ ๋น„์‹ธ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฒŒ์ž„ ์—”์ง„์ฒ˜๋Ÿผ ๋งค ํ”„๋ ˆ์ž„ 16.6ms ์•ˆ์— ์ˆ˜๋งŽ์€ ๊ฐ์ฒด๋ฅผ ๋™๊ธฐํ™”ํ•ด์•ผ ํ•˜๋Š” ํ™˜๊ฒฝ์—์„  ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค + IPC๋ฅผ ์“ธ ์ˆ˜ ์—†๊ณ , ๊ฐ™์€ ํ”„๋กœ์„ธ์Šค ์•ˆ์—์„œ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ + ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ(์Šค๋ ˆ๋“œ ๊ฐ„ ์ž๋™ ๊ณต์œ )๋ฅผ ์„ ํƒํ•  ์ˆ˜๋ฐ–์— ์—†์Šต๋‹ˆ๋‹ค. Chrome์ฒ˜๋Ÿผ ๊ฒฉ๋ฆฌยท๋ณด์•ˆ์ด ์šฐ์„ ์ธ ์˜์—ญ์—์„  IPC ๋น„์šฉ์„ ๊ฐ์ˆ˜ํ•˜๊ณ  ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค๋ฅผ ์“ฐ๋Š” ๊ฑฐ๊ณ ์š”. ๊ฒฉ๋ฆฌ๋Š” ๋น„์‹ธ์ง€๋งŒ ์•ˆ์ „, ๊ณต์œ ๋Š” ๋น ๋ฅด์ง€๋งŒ ์œ„ํ—˜ โ€” ์ด ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๊ฐ€ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

Q18. โ€œWindows ์ž‘์—… ๊ด€๋ฆฌ์ž์—์„œ โ€˜ํ”„๋กœ์„ธ์Šค ์ด๋ฏธ์ง€โ€™๋Š” ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋‚˜์š”?โ€

โ€œ์ด๋ฏธ์ง€(Image)โ€๋Š” ๋””์Šคํฌ์˜ ์‹คํ–‰ ํŒŒ์ผ์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋œ ์ƒํƒœ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” Windows ์šฉ์–ด์ž…๋‹ˆ๋‹ค. Windows ์‹คํ–‰ ํŒŒ์ผ์€ PE(Portable Executable) ํฌ๋งท์ด๊ณ , ์ด๊ฒŒ ๋ฉ”๋ชจ๋ฆฌ์— ๋งคํ•‘๋˜๋ฉด ๊ทธ๊ฑธ โ€œํ”„๋กœ์„ธ์Šค ์ด๋ฏธ์ง€โ€๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

์ž‘์—… ๊ด€๋ฆฌ์ž์—์„œ ๋ณด์ด๋Š” ํ•ญ๋ชฉ๋“ค์ด ์ด ๊ฐœ๋…์„ ์ง์ ‘ ๋“œ๋Ÿฌ๋ƒ…๋‹ˆ๋‹ค โ€” Image Name(์˜ˆ: chrome.exe)์€ ๋””์Šคํฌ์˜ ์‹คํ–‰ ํŒŒ์ผ๋ช…์ด๊ณ , Image Path๋Š” ๊ทธ ํŒŒ์ผ์˜ ๋””์Šคํฌ ๊ฒฝ๋กœ(C:\Program Files\...)์ž…๋‹ˆ๋‹ค. ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€๋ฉด Image Base Address(๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์—์„œ ์ฝ”๋“œ๊ฐ€ ๋กœ๋“œ๋˜๋Š” ์‹œ์ž‘ ์ฃผ์†Œ)๋„ PE ํ—ค๋”์— ๋ช…์‹œ๋ผ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ค์šฉ์ ์œผ๋กœ ์ค‘์š”ํ•œ ์‚ฌ์‹ค ๋‘ ๊ฐ€์ง€ โ€” ์ฒซ์งธ, ํ•˜๋‚˜์˜ ์‹คํ–‰ ํŒŒ์ผ์„ ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Chrome ํƒญ๋งˆ๋‹ค chrome.exe ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋„์›Œ์ง€๋Š” ๊ฒŒ ๊ทธ ์˜ˆ์‹œ์ธ๋ฐ, ๊ฐ ํ”„๋กœ์„ธ์Šค๋Š” ๋…๋ฆฝ๋œ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์„ ๊ฐ–์ง€๋งŒ ์ฝ”๋“œ ํŽ˜์ด์ง€(read-only Text ์˜์—ญ)๋Š” OS๊ฐ€ ๊ฐ™์€ ๋ฌผ๋ฆฌ ํŽ˜์ด์ง€๋ฅผ ๊ณต์œ  ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ™์€ exe 100๊ฐœ๋ฅผ ๋„์›Œ๋„ ์ฝ”๋“œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ํ•œ ๋ฒŒ๋งŒ ๋“ญ๋‹ˆ๋‹ค.

๋‘˜์งธ, Process Explorer(Sysinternals)๋‚˜ tasklist /v ๋ช…๋ น์œผ๋กœ ๋” ์ž์„ธํ•œ ์ด๋ฏธ์ง€ ์ •๋ณด(๋กœ๋“œ๋œ DLL, Image Base, ํ•ธ๋“ค ์ˆ˜ ๋“ฑ)๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋””๋ฒ„๊น…ยท์„ฑ๋Šฅ ๋ถ„์„ํ•  ๋•Œ ์ž์ฃผ ์“ฐ๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ํ•œ๊ตญ์–ด ์œˆ๋„์šฐ ์ž‘์—… ๊ด€๋ฆฌ์ž์—์„  โ€œ์ด๋ฏธ์ง€ ์ด๋ฆ„โ€์œผ๋กœ ๋ฒˆ์—ญ๋ผ ์žˆ์–ด์„œ ์ฒ˜์Œ ๋ณด๋ฉด ์–ด์ƒ‰ํ•˜์ง€๋งŒ, ๋ณธ์งˆ์€ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋œ ์‹คํ–‰ ํŒŒ์ผ์˜ ์ธ์Šคํ„ด์Šค๋ผ๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

Q19. โ€œPCB๋Š” ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์—์„œ ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋‚˜์š”?โ€

PCB(Process Control Block)๋Š” OS ์ปค๋„์ด ํ”„๋กœ์„ธ์Šค ํ•˜๋‚˜๋‹น ํ•˜๋‚˜์”ฉ ์œ ์ง€ํ•˜๋Š” ์ •๋ณด ์ €์žฅ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค. ๋“ค์–ด์žˆ๋Š” ๊ฒŒ ๋งŽ์Šต๋‹ˆ๋‹ค โ€” PID, ๋ฉ”๋ชจ๋ฆฌ ์ •๋ณด(ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šค ์ฃผ์†Œ, ๋ฉ”๋ชจ๋ฆฌ๋งต, ์ฝ”๋“œ/๋ฐ์ดํ„ฐ/ํž™ ์˜์—ญ ์ •๋ณด), ํ•ธ๋“ค ํ…Œ์ด๋ธ”(ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ, ์†Œ์ผ“ ๋“ฑ), ์Šค์ผ€์ค„๋ง ์ •๋ณด(์šฐ์„ ์ˆœ์œ„, ์ƒํƒœ โ€” Ready/Running/Wait), ๋ถ€๋ชจ/์ž์‹ PID, ๊ทธ๋ฆฌ๊ณ  ์†Œ์† ์Šค๋ ˆ๋“œ๋“ค์˜ TCB ๋ฆฌ์ŠคํŠธ.

์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์—์„œ PCB๋Š” โ€œํ”„๋กœ์„ธ์Šค์˜ ๋ชจ๋“  ์ƒํƒœ๋ฅผ ์ž ์‹œ ๋ณด๊ด€ํ•ด๋‘๋Š” ๋ƒ‰์žฅ๊ณ โ€ ์—ญํ• ์ž…๋‹ˆ๋‹ค. ํ๋ฆ„์€ ์ด๋ ‡์Šต๋‹ˆ๋‹ค โ€” โ‘  ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค์˜ ๋ ˆ์ง€์Šคํ„ฐ ์ปจํ…์ŠคํŠธ(PCยทSPยท๋ฒ”์šฉ ๋ ˆ์ง€์Šคํ„ฐ)๋ฅผ PCB(์ •ํ™•ํžˆ๋Š” ๊ทธ ์•ˆ์˜ TCB)์— ์ €์žฅ, โ‘ก OS ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๋‹ค์Œ ํ›„๋ณด ํ”„๋กœ์„ธ์Šค ์„ ํƒ, โ‘ข ๊ทธ ํ”„๋กœ์„ธ์Šค์˜ PCB์—์„œ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šค(CR3)ยทํ•ธ๋“ค ํ…Œ์ด๋ธ”ยท๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ๋ณต์›, โ‘ฃ ์‹คํ–‰ ์žฌ๊ฐœ.

ํ•ต์‹ฌ์€ ํ”„๋กœ์„ธ์Šค ์ „ํ™˜์ด ๋น„์‹ผ ์ด์œ ๊ฐ€ PCB์˜ ๋ณต์› ํ•ญ๋ชฉ์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๋Š” ์ ์ž…๋‹ˆ๋‹ค. ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๋ฒ ์ด์Šค ๊ต์ฒด โ†’ TLB flush โ†’ ์บ์‹œ cold โ†’ ์งํ›„ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ ๋ชจ๋‘ ๋ฏธ์Šค. ๋ฐ˜๋ฉด ์Šค๋ ˆ๋“œ ์ „ํ™˜์€ ๊ฐ™์€ PCB ์•ˆ์—์„œ ๋‹ค๋ฅธ TCB๋กœ ์˜ฎ๊ฒจ๊ฐ€๋Š” ๊ฒƒ์ด๋ผ ํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”ยทํ•ธ๋“ค์€ ๊ทธ๋Œ€๋กœ ๋‘๊ณ  ๋ ˆ์ง€์Šคํ„ฐ๋งŒ ๊ต์ฒดํ•ฉ๋‹ˆ๋‹ค โ€” ๊ทธ๋ž˜์„œ 5~10๋ฐฐ ๋น ๋ฅธ ๊ฑฐ๊ณ ์š”. PCB์™€ TCB์˜ ํฌ๊ธฐ ์ฐจ์ด(PCB ์ˆ˜ KB / TCB ์ˆ˜๋ฐฑ ๋ฐ”์ดํŠธ)๊ฐ€ ์ด ๋น„์šฉ ์ฐจ์ด์˜ ์ง์ ‘์  ์›์ธ์ž…๋‹ˆ๋‹ค.


ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ (์žฌ๊ฒŒ์žฌ)

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
38
39
40
41
42
43
44
45
46
47
ํ”„๋กœ์„ธ์Šค = ์ž์› ์†Œ์œ  ๋‹จ์œ„ (๋ฉ”๋ชจ๋ฆฌยทํ•ธ๋“คยท๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„ ๋…๋ฆฝ)
์Šค๋ ˆ๋“œ   = ์‹คํ–‰ ํ๋ฆ„ ๋‹จ์œ„ (์ฝ”๋“œยท๋ฐ์ดํ„ฐยทํž™ ๊ณต์œ , ์Šคํƒยท๋ ˆ์ง€์Šคํ„ฐ๋งŒ ๋…๋ฆฝ)

์ฐจ์ด 3๊ฐ€์ง€:
  โ‘  ์ž์› ์†Œ์œ    โ€” ํ”„๋กœ์„ธ์Šค ๋…๋ฆฝ / ์Šค๋ ˆ๋“œ ๊ณต์œ 
  โ‘ก ์ปจํ…์ŠคํŠธ   โ€” ํ”„๋กœ์„ธ์Šค ๋น„์Œˆ(TLB flushยทํŽ˜์ด์ง€ ํ…Œ์ด๋ธ” ๊ต์ฒด) / ์Šค๋ ˆ๋“œ 5~10๋ฐฐ ๋น ๋ฆ„
  โ‘ข ํ†ต์‹        โ€” IPC vs ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ (์†๋„์™€ ์•ˆ์ „์„ฑ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„)

๋ฉ”๋ชจ๋ฆฌ 4์˜์—ญ:
  Code (๊ณต์œ ) / Data (๊ณต์œ ) / Heap (๊ณต์œ ) / Stack (์Šค๋ ˆ๋“œ๋ณ„ ๋…๋ฆฝ)

PCB vs TCB:
  PCB = ํ”„๋กœ์„ธ์Šค ์ •๋ณด (PIDยทํŽ˜์ด์ง€ ํ…Œ์ด๋ธ”ยทํ•ธ๋“คยท๋ฉ”๋ชจ๋ฆฌ๋งต)        โ€” ํผ
  TCB = ์Šค๋ ˆ๋“œ ์ •๋ณด  (TIDยท๋ ˆ์ง€์Šคํ„ฐยทSPยทPC)                       โ€” ์ž‘์Œ

๋™๊ธฐํ™”:
  race condition  โ€” ๋™์‹œ ์ ‘๊ทผ์œผ๋กœ ๋น„๊ฒฐ์ •์  ๊ฒฐ๊ณผ
  mutex / atomic / condition_variable  ๋กœ ํ•ด๊ฒฐ
  RAII ๋ฝ: std::lock_guard / std::scoped_lock / FScopeLock  (9๋ฒˆ RAII ํšŒ๊ท€)
  deadlock 4์กฐ๊ฑด โ€” ์ƒํ˜ธ ๋ฐฐ์ œยท์ ์œ  ๋Œ€๊ธฐยท๋น„์„ ์ ยท์ˆœํ™˜ ๋Œ€๊ธฐ

์Šค๋ ˆ๋“œ ๋ชจ๋ธ:
  1:1  std::thread, pthread, Windows Thread  (๊ฐ€์žฅ ์ผ๋ฐ˜)
  N:1  green thread (์—ญ์‚ฌ์ )
  M:N  Go goroutine, Java Loom virtual thread  (์ตœ์‹ )

์„ ํƒ ๊ธฐ์ค€:
  ๊ฒฉ๋ฆฌยท์•ˆ์ •์„ฑยท๋ณด์•ˆ     โ†’ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค (Chrome, Postgres)
  ์†๋„ยทํ†ต์‹ ยท์ž์› ํšจ์œจ  โ†’ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ  (๊ฒŒ์ž„ ์—”์ง„, ์›Œ์ปค ํ’€)

C++ API:
  std::thread / std::jthread (C++20)
  std::mutex + std::lock_guard / std::scoped_lock (C++17)
  std::atomic<T>
  std::async / std::future
  std::condition_variable

์–ธ๋ฆฌ์–ผ:
  ๊ฒŒ์ž„ ์Šค๋ ˆ๋“œ (Tick, UObject)
  ๋ Œ๋” ์Šค๋ ˆ๋“œ (RHI ๋ช…๋ น)
  FRunnable + FRunnableThread     โ€” std::thread ๋Œ€์‘
  AsyncTask / ParallelFor          โ€” ํ’€ ๋””์ŠคํŒจ์น˜ / ๋ณ‘๋ ฌ ๋ฃจํ”„
  FCriticalSection + FScopeLock   โ€” std::mutex + lock_guard ๋Œ€์‘
  TAtomic / FEvent
  check(IsInGameThread())          โ€” ์Šค๋ ˆ๋“œ ์•ˆ์ „ ์œ„๋ฐ˜ ๊ฒ€์ถœ

๊ฒŒ์ž„ ์—”์ง„์ด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์“ฐ๋Š” ์ด์œ : 60fps (16.6ms/ํ”„๋ ˆ์ž„) โ†’ IPC ๋น„์šฉ ๋ชป ๊ฒฌ๋”ค

ํšŒ๊ท€ ๋‹ค๋ฆฌ โ€” ๋‹ค๋ฅธ CS ํŒŒ์ผ ์—ฐ๊ฒฐ

| ํŒŒ์ผ | ์—ฐ๊ฒฐ ์ง€์  | |โ€”|โ€”| | 01_runtime | ๋ฉ”๋ชจ๋ฆฌ 4์˜์—ญ(Code/Data/Heap/Stack)์ด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ์˜ ์ถœ๋ฐœ์ . Stack๋งŒ ์Šค๋ ˆ๋“œ๋ณ„ ๋…๋ฆฝ, ๋‚˜๋จธ์ง€๋Š” ๊ณต์œ  | | 03_new_vs_malloc | ํž™ ํ• ๋‹น์ด ์Šค๋ ˆ๋“œ ๊ฐ„ ๊ณต์œ  ์ž์›. new ์ž์ฒด๋Š” ์Šค๋ ˆ๋“œ ์•ˆ์ „(๋ณดํ†ต)ํ•˜์ง€๋งŒ ํ• ๋‹น๋œ ๊ฐ์ฒด ์ ‘๊ทผ์€ ๋™๊ธฐํ™” ํ•„์š” | | 09_rtti_raii | RAII๊ฐ€ mutex ๋ฝ์—์„œ๋„ ๊ทธ๋Œ€๋กœ โ€” std::lock_guard, std::scoped_lock, FScopeLock์€ 9๋ฒˆ RAII์˜ ๋™์‹œ์„ฑ ์‘์šฉ | | 11_smart_pointer | shared_ptr ์ œ์–ด ๋ธ”๋ก์˜ reference count๊ฐ€ atomic์œผ๋กœ ๊ตฌํ˜„๋จ. ์นด์šดํ„ฐ๋Š” thread-safe, ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด๋Š” ๋ณ„๋„ ๋ณดํ˜ธ ํ•„์š” | | 16_stl_containers | STL ์ปจํ…Œ์ด๋„ˆ์˜ ์Šค๋ ˆ๋“œ ์•ˆ์ „์„ฑ ์ปจ๋ฒค์…˜ โ€” ๊ฐœ๋ณ„ ์ปจํ…Œ์ด๋„ˆ๋Š” thread-safeํ•˜์ง€ ์•Š์Œ. ์™ธ๋ถ€ mutex ๋˜๋Š” ๋™์‹œ์„ฑ ์ž๋ฃŒ๊ตฌ์กฐ ์‚ฌ์šฉ | | 18_list_sort | ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋„๋ฉ”์ธ์˜ ๋งˆ์ง€๋ง‰ โ€” 19๋ฒˆ์—์„œ OS ๋„๋ฉ”์ธ์œผ๋กœ ์ „ํ™˜๋˜๋Š” ๋ถ„๊ธฐ์  | ```

์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

ยฉ GoldBoll. ์ผ๋ถ€ ๊ถŒ๋ฆฌ ๋ณด์œ 

Powered by Jekyll with Chirpy theme

์ธ๊ธฐ ํƒœ๊ทธ