TL;DR
- thread๋ ํ๋์จ์ดยทOSยทuser ์ธ ์ธต์๋ผ ์ด๋ฆ๋ง ๊ฐ์ ๋จผ์ ๊ตฌ๋ถ์ด ํ์
- ๋์์ฑ์ ๊ฒน์ณ ๋ค๋ฃจ๋ ๊ตฌ์กฐ, ๋ณ๋ ฌ์ฑ์ ์ฌ๋ฌ ์ฝ์ด์ ์ค์ ๋์ ์คํ โ I/O-bound๋ ๋์์ฑ, CPU-bound๋ ๋ณ๋ ฌ๋ก ํด๊ฒฐ
- ์คํ ๋ชจ๋ธ์ preemptive(OS thread)ยทcooperative(event loop)ยทM:N(goroutine) ์ธ ๊ฐ๋
AI-assisted
1. CPU๋ ํ ๋ฒ์ ํ๋์ฉ ์คํ
CPU ์ฝ์ด ํ๋๋ ๋ช ๋ น์ด๋ฅผ ์์ฐจ์ ์ผ๋ก ์คํํ๋ค. ํ ์๊ฐ์ ์งํ๋๋ ์คํ ํ๋ฆ์ ํ๋๋ฟ์ด๋ค. ํ์ค์ ์๊ตฌ๋ ๋ค๋ฅด๋ค.
- ์น ์๋ฒ๋ ์์ฒ ๋ช ์ ์์ฒญ์ ๋์์ ๋ฐ์์ผ ํ๋ค
- ํฌ๋กค๋ฌ๋ ์๋ฐฑ ๊ฐ์ URL์ ๋์์ ์์งํ๋ ค ํ๋ค
- ํ ํ๋ก๊ทธ๋จ์ด ํ์ผ์ ์ฝ๋ ๋์ ๋คํธ์ํฌ ์์ฒญ๋ ๋ณด๋ด์ผ ํ๋ค
OS๋ CPU ์๊ฐ์ ์๊ฒ ์ชผ๊ฐ ์ฌ๋ฌ ์์
์ ๋ฒ๊ฐ์ ๋๋ ์ค์ผ๋ก์จ ์ด ์๊ตฌ๋ฅผ ๋ฉ์ด๋ค.
์ฝ์ด ํ๋์์ ๋งค ์๊ฐ ๋๋ ํ๋ฆ์ ํ๋์ง๋ง ์ ํ์ด ์ถฉ๋ถํ ๋น ๋ฅด๋ฉด ์ฌ๋ฌ ์์
์ด ํจ๊ป ์งํ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค.
๋ฌผ๋ฆฌ ์ฝ์ด์ ๋ ผ๋ฆฌ ์ฝ์ด โ SMT
์ต์ CPU๋ ๋ฌผ๋ฆฌ ์ฝ์ด ํ๋๋ฅผ ๋ ผ๋ฆฌ ์ฝ์ด ๋ ๊ฐ์ฒ๋ผ ๋ณด์ด๊ฒ ํ๋ ๊ธฐ์ ์ ๊ฐ๋๋ค(์ธํ ์ ํ์ดํผ์ค๋ ๋ฉ, ์ผ๋ฐ์ ์ผ๋ก SMT).
โ4์ฝ์ด 8์ค๋ ๋โ CPU๋ ๋ฌผ๋ฆฌ ์ฝ์ด๊ฐ 4๊ฐ์ง๋ง OS์๋ ๋ ผ๋ฆฌ ์ฝ์ด๊ฐ 8๊ฐ๋ก ๋ณด์ธ๋ค. ๋ ผ๋ฆฌ ์ฝ์ด๊ฐ ๋ง์์๋ก ๋ ๋ง์ ํ๋ฆ์ ๋์์ ๋ฐฐ์นํ ์ ์์ผ๋, ๊ฐ์ ๋ฌผ๋ฆฌ ์ฝ์ด์ ์คํ ์์์ ๋๋ ์ฐ๋ฏ๋ก ์ฑ๋ฅ์ด ๋ฌผ๋ฆฌ ์ฝ์ด ์์ ๋ฐฐ์๋งํผ ๋์ง๋ ์๋๋ค. ์ด โ8์ค๋ ๋โ์ ์ค๋ ๋๊ฐ ๋ค์ ์ ์์ ๊ตฌ๋ถํ ํ๋์จ์ด thread๋ค.
2. ์คํ ๋จ์ โ process, thread, coroutine
"์ค๋ ๋"๋ผ๋ ๋ง์ ์ธ ์ธต์
๊ฐ์ ๋จ์ด๊ฐ ์์ ํ ๋ค๋ฅธ ์ธต์๋ฅผ ๊ฐ๋ฆฌํจ๋ค. ์ด๋ฆ๋ง ๊ฐ์ ํท๊ฐ๋ฆฌ๊ธฐ ์ฌ์ฐ๋ ๋จผ์ ์ง๊ณ ๊ฐ๋ค.
- ํ๋์จ์ด thread: ์์์ ์ธ๊ธํ โ4์ฝ์ด 8์ค๋ ๋โ์ ๊ทธ ์ค๋ ๋. ๋ ผ๋ฆฌ ์ฝ์ด์ ๊ฐ์ ๋ง์ด๊ณ , CPU ์คํ์ผ๋ก ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ ํด์ง๋ค.
- OS thread(kernel-level thread): ํ๋ก๊ทธ๋จ์ด ๋ง๋ค๊ณ kernel์ด ์ธ์ยท์ค์ผ์ค๋งํ๋ ์คํ ํ๋ฆ(
threading.Thread, pthread ๋ฑ). ๊ฐ์ ์ ํ์ด ์๋ค.- user thread(user-level thread): kernel์ ๋ชจ๋ฅด๊ณ user space ๋ฐํ์์ด ๊ตด๋ฆฌ๋ ๊ฒฝ๋ ์คํ ํ๋ฆ. ์๋ coroutine๊ณผ 10์ goroutine์ด ์ฌ๊ธฐ ์ํ๋ค.
์์ผ๋ก ๊ทธ๋ฅ โthreadโ๋ผ๊ณ ํ๋ฉด kernel์ด ์ค์ผ์ค๋งํ๋ OS thread๋ฅผ ๊ฐ๋ฆฌํจ๋ค.
OS๋ ์ด OS thread๋ค์ ๋ ผ๋ฆฌ ์ฝ์ด(ํ๋์จ์ด thread)์ ๋ฒ๊ฐ์ ์ฌ๋ฆฌ๊ณ , ๋ ผ๋ฆฌ ์ฝ์ด ํ๋๊ฐ ํ ์๊ฐ์ ์คํํ๋ OS thread๋ ํ๋๋ฟ์ด๋ค.
user thread๋ ์ด OS thread์ ์นํ์ ๋๋ค.
โ์ฌ๋ฌ ์ผโ์ ๋ด๋ ์คํ ๋จ์๋ ์ธ ์ธต์๋ค.
- process: ์คํ ์ค์ธ ํ๋ก๊ทธ๋จ์ ์ธ์คํด์ค
- ๊ฐ process๋ ์๊ธฐ๋ง์ ๋ ๋ฆฝ๋ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ด ์์
- ๋ค๋ฅธ process์ ๋ฉ๋ชจ๋ฆฌ์๋ ์ง์ ์ ๊ทผํ ์ ์๊ณ , ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ผ๋ ค๋ฉด IPC(ํ์ดํ, ์์ผ, ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๋ฑ)๊ฐ ํ์
- thread: process ์์ ๋ ์์ ์คํ ํ๋ฆ
- ๊ฐ์ process์ thread๋ค์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํต์งธ๋ก ๊ณต์ (ํ, ์ ์ญ ๋ณ์). ๋ค๋ง ๊ฐ thread๋ ์๊ธฐ๋ง์ ์คํ๊ณผ ๋ ์ง์คํฐ, program counter๋ฅผ ๋ฐ๋ก ๊ฐ์ง
- OS(์ ํํ๋ kernel)๊ฐ ์ธ์ํ๊ณ ์ค์ผ์ค๋งํ๋ ์ต์ ๋จ์
- coroutine: thread๋ณด๋ค ํ ๊ฒน ์์ชฝ์ ์คํ ๋จ์
- ์ค๊ฐ์ ๋ฉ์ท๋ค๊ฐ ๋์ค์ ๊ทธ ์๋ฆฌ์์ ์ฌ๊ฐํ ์ ์๋ ํจ์๋ก, kernel์ ์ด ์กด์ฌ๋ฅผ ๋ชจ๋ฅด๊ณ ํ๋์ thread ์์์ ํ๋ก๊ทธ๋จ(๋ฐํ์)์ด ์ค์ค๋ก ๊ด๋ฆฌ
- ์์์ ๋งํ user thread์ ๋ํ์ ์ธ ํํ์ด๋ฉฐ, ์์ธํ ๋์์ 9์ event loop์์ ๋ค๋ฃธ
| process | thread | |
|---|---|---|
| ๋ฉ๋ชจ๋ฆฌ | ๋ ๋ฆฝ(๊ฒฉ๋ฆฌ) | ๊ฐ์ process ์์์ ๊ณต์ |
| ํต์ | IPC ํ์ | ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ก ๋ฐ๋ก |
| ์์ฑ ๋น์ฉ | ๋ฌด๊ฑฐ์ | ์๋์ ์ผ๋ก ๊ฐ๋ฒผ์ |
| ํ์ชฝ์ด ์ฃฝ์ผ๋ฉด | ๋ค๋ฅธ process ์ํฅ ์ ์ | process ์ ์ฒด ์ํ |
๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๋์ง ์ฌ๋ถ๊ฐ ๋ค์์ ๋ค๋ฃฐ race condition๊ณผ ๋ณ๋ ฌํ ์ ๋ต์ ๊ฐ๋ฅธ๋ค.
์ ์ โ๋ฌด์์ ์๊ธฐ ๊ฒ์ผ๋ก ์์ ํ๋๋โ๋ก ๋ณด๋ฉด, ๋ชจ๋ ์คํ ์ํ๋ฅผ ๋ด์ ๊ตฌ์ฒด์ ๊ฐ์ฒด์ด๋ ์์ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋๋ก ๊ฐ์๋ก ์ข์์ง๋ค.
| ์คํ ๋จ์ | ์๊ธฐ ๊ฒ์ผ๋ก ์์ | ๊ณต์ ํ๋ ๊ฒ | ๊ด๋ฆฌ ์ฃผ์ฒด |
|---|---|---|---|
| process | ๋ ๋ฆฝ ์ฃผ์ ๊ณต๊ฐ, ํ์ผ ๋์คํฌ๋ฆฝํฐ | ์์(๊ฒฉ๋ฆฌ) | kernel |
| thread | ์๊ธฐ ์คํ + ๋ ์ง์คํฐยทPC | ์์ process์ ์ฃผ์ ๊ณต๊ฐ | kernel |
| coroutine | ์๊ธฐ frame(์ง์ญ ๋ณ์ + ์ฌ๊ฐ ์ง์ ) | ์์ thread์ ์คํยทํ ์ ๋ถ | user space ๋ฐํ์ |
process๋ ๊ฒฉ๋ฆฌ๋ ๊ณต๊ฐ์ ํต์งธ๋ก, thread๋ ๊ทธ ์์์ ์คํ ์ปจํ
์คํธ(์คํยท๋ ์ง์คํฐ)๋ง, coroutine์ ๋ ์์ชฝ์์ ์ค๋จ๋ frame๋ง ์๊ธฐ ๊ฒ์ผ๋ก ๋ ๋ค.
coroutine๋ ์ถ์ ๊ฐ๋
์ด ์๋๋ผ โ์ค๋จ ์ํ๋ฅผ ๋ด์ ์ค์ ๊ฐ์ฒดโ(Python์์ async def ํธ์ถ์ด ๋๋ ค์ค)์ด๋ค.
3. ์ดํด๋ฅผ ์ํ ๋น์
์ด ๊ธ์ ์ดํ์ ๋ชจ๋ ์ค๋ช ์ ํ๋์ ๋น์ ์์์ ํ๋ค. ์ฌ๋ฌด์ค์์ ์ผ๊พผ๋ค์ด ์๋ฅ๋ฅผ ์ฒ๋ฆฌํ๋ ๊ทธ๋ฆผ์ด๋ค.
| ๋น์ | ์ค์ฒด | ํต์ฌ ์ฑ์ง |
|---|---|---|
| ์ฌ๋ฌด์ค | process | ์๊ธฐ ์ฑ ์(์ฃผ์ ๊ณต๊ฐ)๊ณผ ์์์ ๊ฐ์ง. ์ฌ๋ฌด์ค๋ผ๋ฆฌ๋ ๊ฒฉ๋ฆฌ |
| ์ ๋ฌด ํด๋ | OS thread | ๋ถ๋งํฌ(program counter)์ ์ค๊ฐ ๋ฉ๋ชจ(์คํยท๋ ์ง์คํฐ)๋ฅผ ํ์ |
| ํด๋ ์ ์๊ฑด | coroutine (user thread) | ์๊ฑด๋ง๋ค ์์ฒด ๋ถ๋งํฌ. ํด๋ ์์์๋ง ์ค๊ฐ |
| ์ผ๊พผ์ ์ | ๋ ผ๋ฆฌ ์ฝ์ด(ํ๋์จ์ด thread) | ํ ์๊ฐ์ ํด๋ ํ๋๋ง ์ก์ |
| ๊ด๋ฆฌ์ | OS scheduler | ์ด๋ ์์ ์ด๋ ํด๋๋ฅผ ์ฅ์ฌ์ค์ง ๋ฐฐ์ |
| ์ฒ๋ฆฌ ๋๊ธฐ ๋ฐ๊ตฌ๋ | run queue | ์ค๋น๋ ํด๋๊ฐ ์์ ๊ธฐ๋ค๋ฆฌ๋ ์ค. ์(์ฝ์ด)๋ง๋ค ํ๋์ฉ |
| ๋ณด๋ฅํจ | wait queue | ์ธ๋ถ ๋ต๋ณ์ ๊ธฐ๋ค๋ฆฌ๋๋ผ ์์ง ์ฒ๋ฆฌ ๋ชป ํ๋ ํด๋๊ฐ ๊ฐ๋ ๊ณณ |
ํด๋(thread)๋ ์๋ฐฑ ์ฅ, ์ผ๊พผ์ ์(๋
ผ๋ฆฌ ์ฝ์ด)์ ๋ช ๊ฐ๋ฟ์ด๋ค.
ํ ์์ด ํด๋ A๋ฅผ ์ ๊น ์ฒ๋ฆฌํ๋ค ๋ถ๋งํฌ๋ฅผ ๋จ๊ธฐ๊ณ ๋ด๋ ค๋๊ณ ํด๋ B๋ฅผ ์ง๋๋ค. ๋์ค์ A๋ฅผ ๋ค์ ์ง์ผ๋ฉด ๋ถ๋งํฌ๋ถํฐ ์ด์ด๊ฐ๋ค.
์ด โ๋ด๋ ค๋๊ณ ๋ถ๋งํฌ ๋จ๊ธฐ๊ธฐโ๊ฐ 5์ ์ context switch๋ค.
ํด๋ ์์๋ ์ฌ๋ฌ ์๊ฑด(coroutine)์ด ๋ค์ด ์์ ์ ์๋ค.
์ผ๊พผ์ด ํด๋๋ฅผ ์ก์ผ๋ฉด ๊ทธ ์ ์๊ฑด๋ค์ ๋ฒ๊ฐ์ ์ฒ๋ฆฌํ๋๋ฐ ํด๋๋ฅผ ๋ฐ๊พธ๋ ์ผ์ ๊ด๋ฆฌ์(kernel)๊ฐ ๊ฐ์ ํ ์ ์์ง๋ง ํด๋ ์ ์๊ฑด์ ๋ฐ๊พธ๋ ์ผ์ ํ๋ก๊ทธ๋จ์ด ํด๋ ๋ด๋ถ์์ ์์์ ํ๋ค. kernel์ ํด๋ ๋จ์๊น์ง๋ง ์๋ค.
4. thread์ ์ธ ๊ฐ์ง ์ํ
์ผํ์ง ์๋ ํด๋์๋ ์ข ๋ฅ๊ฐ ์๋ค. thread๋ ๋ ์ ์ค ํ๋์ ์ํ์ ์๋ค.
- Running: ์ง๊ธ ์ด๋ค ์ฝ์ด์์ ์ค์ ๋ก ๋๊ณ ์์ (์ผ๊พผ ์์ ๋ค๋ฆฐ ํด๋)
- Runnable: ๋ ์ค๋น๋ ๋๋๋ฐ ์ฝ์ด๋ฅผ ๋ชป ์ป์ด run queue์์ ์ฐจ๋ก๋ฅผ ๊ธฐ๋ค๋ฆผ (์ฒ๋ฆฌ ๋๊ธฐ ๋ฐ๊ตฌ๋ ์ ํด๋). ์ฝ์ด๋ง ๋๋ฉด ์ฆ์ ์คํ
- Blocked: I/O๋ ์ด๋ฒคํธ๋ฅผ ๊ธฐ๋ค๋ ค ์ง๊ธ์ ๋ ์ ์์ (๋ณด๋ฅํจ ์ ํด๋). run queue์๋ ์์
run queue๋ ๋ณดํต ๋ ผ๋ฆฌ ์ฝ์ด๋ง๋ค ํ๋์ฉ ์๋ค(per-core run queue). ๊ด๋ฆฌ์(scheduler)๋ ์ด๋ ์ฝ์ด์ ๋ฐ๊ตฌ๋์ ํด๋๋ฅผ ๋ฃ์์ง ๋ฐฐ์ ํ๊ณ , ๊ฐ ์ฝ์ด๋ ์๊ธฐ ๋ฐ๊ตฌ๋์์ ๋ค์ ํด๋๋ฅผ ๊บผ๋ด ์ฒ๋ฆฌํ๋ค.
๋ฐ๊ตฌ๋๊ฐ ์ฑ์์ง๋ ๊ฒฝ๋ก๋ ์ ์ด๋ค. ์๋ก ์์ฑ๋ thread, ์ ์ ๋นํด ๋ด๋ ค์จ thread, ๋ณด๋ฅํจ์์ ๋ต๋ณ์ด ์ ๊นจ์ด๋ thread๋ค.
์ํ ์ ์ด๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ๋ํ๋ด๋ฉด ์ด๋ ๋ค.
stateDiagram-v2 [*] --> Runnable: ์์ฑ Runnable --> Running: ์ค์ผ์ค๋ฌ๊ฐ ๋์คํจ์น Running --> Runnable: preemption ยท ํ์์์ Running --> Blocked: blocking I/O ยท ์ด๋ฒคํธ ๋๊ธฐ Blocked --> Runnable: I/O ์๋ฃ ยท ์ด๋ฒคํธ ๋์ฐฉ Running --> [*]: ์ข ๋ฃ
์ ํ์๋ ๋ ๊ณ๊ธฐ๊ฐ ์๊ณ , ์ด ๋์ด ์์ ํ ๋ค๋ฅด๋ค.
- preemption(์ ์ ): Running์์ ์๊ฐ ํ ๋น๋(time slice)์ด ๋๋ kernel์ด ๊ฐ์ ๋ก ๋บ์
- run queue๋ก ๋ฐ๋ก ๋์๊ฐ(Runnable)
- ํ ์ผ์ ๋จ์๊ณ ์ฝ์ด๋ง ๋๋ฉด ๋ค์ ์คํ
- blocking(๋๊ธฐ): thread๊ฐ blocking I/O๋ ๋ฝ์ ์ง์ ํธ์ถํด ์ค์ค๋ก ์งํ ๋ชป ํ๊ฒ ๋จ
- ๋ณด๋ฅํจ์ผ๋ก ์ด๋(Blocked).
- ๊ธฐ๋ค๋ฆฌ๋ ์ด๋ฒคํธ๊ฐ ์์ผ ๋น๋ก์ Runnable๋ก ๋ณต๊ท
Blocked๋ kernel์ด โ์๋ I/O๋ฅผ ์์ฃผ ํ๋ ๋ฏธ๋ฆฌ ์ฌ์ฐ์โ๊ณ ์์ธกํด์ ๋ง๋๋ ์ํ๊ฐ ์๋๋ค. thread๊ฐ blocking ์ฐ์ฐ์ ์ค์ ๋ก ์คํํ๋ ์๊ฐ์๋ง ์ผ์ด๋๋ค.
thread์ ๊ณผ๊ฑฐ ์ด๋ ฅ์ ์ฐ์ ์์ ์กฐ์ ์๋ง ์ฐ์ผ ๋ฟ, ์ํ๋ฅผ ๊ฐ์ ๋ก Blocked๋ก ๋ฐ๊พธ์ง ์๋๋ค.
5. context switch โ ์ ํ์ ๋น์ฉ๊ณผ ๋จ์
๊ด๋ฆฌ์๊ฐ ํด๋๋ฅผ ๋ฐ๊พธ๋ ์ผ์๋ ๋น์ฉ์ด ๋ ๋ค.
OS scheduler๋ CPU ์๊ฐ์ ์๊ฒ ์ชผ๊ฐ ์ฌ๋ฌ thread์ ๋ฒ๊ฐ์ ํ ๋นํ๋๋ฐ(preemptive multitasking), ์ ํํ ๋ kernel์ ๋ ๊ฐ์ง๋ฅผ ํ๋ค.
- ์ง๊ธ ๋๋ thread์ ์ํ(๋ ์ง์คํฐ, ์คํ ํฌ์ธํฐ, program counter)๋ฅผ ์ ์ฅํ๋ค
- ๋ค์ thread์ ์ํ๋ฅผ ๋ณต์ํด ์ด์ด์ ์คํํ๋ค
์ด ์ ์ฅยท๋ณต์ ๊ณผ์ ์ด context switch๋ค. ๋ ํน์ง์ด ์ค์ํ๋ค.
- kernel์ด ๊ฐ์ ๋ก ์ํํ๋ค. ์คํ ์ค์ธ ์ฝ๋๋ ์์ ์ด ์ธ์ ๋ฉ์ถ์ง ๋ชจ๋ฅธ๋ค. ํ์ด๋จธ ์ธํฐ๋ฝํธ๋ก OS๊ฐ ๋ผ์ด๋ค์ด ํ๋ฆ์ ๋ฐ๊พผ๋ค.
- ๋น์ฉ์ด ๋ ๋ค. ์ํ ์ ์ฅยท๋ณต์์ ์ง์ ๋น์ฉ์ ๋ํด, CPU ์บ์๊ฐ ๋ฌดํจํ๋๋ ๊ฐ์ ๋น์ฉ์ด ๋ฐ๋ฅธ๋ค. thread๋ฅผ ์์ฒ ๊ฐ์ฉ ๋์ฐ๋ฉด ์ผํ๋ ์๊ฐ๋ณด๋ค ์ ํํ๋ ์๊ฐ์ด ๋์ด ์คํ๋ ค ๋๋ ค์ง ์ ์๋ค.
์ ํ์ ๋จ์๋ thread, ๋น์ฉ์ process ๊ฒฝ๊ณ์์ ์ปค์ง๋ค
์ ํ์ ์ค์ ๋์์ process๊ฐ ์๋๋ผ thread๋ค.
kernel ๊ด์ ์์ thread์ process๋ ์ฌ์ค์ ๊ฐ์ ์ค์ผ์ค ๋จ์๋ก ํํ๋๊ณ (๋ฆฌ๋ ์ค์์ ๋ ๋คtask_struct), scheduler๋ ์ด ๋จ์๋ฅผ ์ฝ์ด์ ์ฌ๋ฆฌ๊ณ ๋ด๋ฆฐ๋ค. process๋ ์ฃผ์ ๊ณต๊ฐยทํ์ผ ๋์คํฌ๋ฆฝํฐ ๊ฐ์ ์์์ ๋ด๋ ์ปจํ ์ด๋์ผ ๋ฟ์ด๋ผ, ๊ด๊ฑด์ ์ง๊ธ ์ ํํ๋ thread๊ฐ ์ด๋ process์ ์ํ๋๋๋ค.
- ๊ฐ์ process์ thread๋ผ๋ฆฌ: ์ฃผ์ ๊ณต๊ฐ์ ๊ณต์ ํ๋ฏ๋ก ๋ ์ง์คํฐยท์คํ ํฌ์ธํฐยทPC๋ง ๊ฐ์ ๋ผ์ฐ๋ฉด ๋๋ค. ๊ฐ๋ณ๋ค.
- ๋ค๋ฅธ process์ thread๋ก: ์ฌ๊ธฐ์ ์ฃผ์ ๊ณต๊ฐ ์ ํ(page table ๊ต์ฒด, TLB flush)์ด ์นํ ๋ ๋น์ธ๋ค. โprocess ๊ฐ ์ ํ์ด ๋ฌด๊ฒ๋คโ๋ ๋ง์ process ์์ฒด๋ฅผ ๋ฐ๊ฟ์๊ฐ ์๋๋ผ, ๋ค๋ฅธ process์ thread๋ก ๋์ด๊ฐ๋ฉฐ ์ฃผ์ ๊ณต๊ฐ๊น์ง ๋ฐ๋๊ธฐ ๋๋ฌธ์ด๋ค.
์ ํ ๋น์ฉ์ ์ค์ด๋ ค๋ ๋ํ ์ฅ์น๊ฐ cache affinity๋ค.
scheduler๋ thread๋ฅผ ์ด์ ์ ๋๋ ์ฝ์ด์ ๋ค์ ์ฌ๋ฆฌ๋ ค ํ๋ค. ๊ทธ ์ฝ์ด์ ์บ์์ ์ด thread๊ฐ ์ฐ๋ ๋ฐ์ดํฐ๊ฐ ์์ง ๋จ์(warm cache) ์์ ๊ฐ๋ฅ์ฑ์ด ๋๊ธฐ ๋๋ฌธ์ด๋ค.
๋ค๋ง ์บ์๋ ์ฉ๋์ด ์ฐจ๋ฉด ์ค๋๋ ๊ฒ๋ถํฐ ๋ฐ๋ ค๋๋ฏ๋ก(๋๋ต LRU), ๋๋ฌด ์ค๋ ์ง๋ฌ๊ฑฐ๋ ๊ทธ ์ฌ์ด ๋ค๋ฅธ thread๊ฐ ๊ทธ ์ฝ์ด๋ฅผ ํ์ ์์ผ๋ฉด ์ด๋ฏธ ์์ด(cold cache) ์ด๋์ด ์ฌ๋ผ์ง๋ค.
๊ทธ๋์ cache affinity๋ ํ์ ๋ณด์ฅ์ด ์๋๋ผ ํ๋ฅ ์ ํธํฅ์ด๋ฉฐ, ๋ถํ๊ฐ ํ์ชฝ์ ๋ชฐ๋ฆฌ๋ฉด scheduler๋ ์บ์ ์ด๋์ ํฌ๊ธฐํ๊ณ thread๋ฅผ ๋ค๋ฅธ ์ฝ์ด๋ก ์ฎ๊ธด๋ค.
์ด๊ฒ์ด ํํ ๋งํ๋ โOS ๋ ๋ฒจ context switchโ๋ค. kernel์ด ์ฃผ๋ํ๊ณ , ๋ฌด๊ฒ๊ณ , ์คํ ์ค์ธ ์ฝ๋๋ ํต์ ํ ์ ์๋ค.
์ดํ์ ์๊ฐํ event loop๋ goroutine์ ์ ํ๊ณผ๋ ์ฑ๊ฒฉ์ด ๋ค๋ฅด๋ค.
6. ๋์์ฑ๊ณผ ๋ณ๋ ฌ์ฑ
๋์์ฑ๊ณผ ๋ณ๋ ฌ์ฑ์ ๋น์ทํด ๋ณด์ด์ง๋ง ๋ค๋ฅธ ๊ฐ๋ ์ด๋ค. ์ด ๋์ ๊ตฌ๋ถํ์ง ๋ชปํ๋ฉด ์ดํ์ ๋๊ตฌ ์ ํ์ด ์ ๋ถ ํ๋ ค์ง๋ค.
- concurrency(๋์์ฑ)๋ ์ฌ๋ฌ ์์
์ ๊ฒน์ณ์ ๋ค๋ฃจ๋ ๋ฅ๋ ฅ์ด๋ค.
- ํ ์๊ฐ์ ๋ ผ๋ฆฌ ์ฝ์ด ํ๋๊ฐ ํ ๊ฐ์ง ์ผ๋ง ํ๋๋ผ๋, ์์ A๋ฅผ ์กฐ๊ธ ํ๋ค B๋ก ๋์ด๊ฐ๊ณ ๋ค์ A๋ก ๋์์ค๋ ์์ผ๋ก ๊ตฌ์ฑํ๋ฉด ๋ฐ์์ ๋ณด๊ธฐ์ ์ฌ๋ฌ ์ผ์ด ํจ๊ป ์งํ
- ์ฝ์ด๊ฐ ํ๋๋ฟ์ด์ด๋ ๋์์ฑ์ ์ฑ๋ฆฝ
- parallelism(๋ณ๋ ฌ์ฑ)์ ์ฌ๋ฌ ์์
์ด ์ค์ ๋ก ๊ฐ์ ์๊ฐ์ ์๋ก ๋ค๋ฅธ ์ฝ์ด์์ ์คํ๋๋ ๊ฒ์ด๋ค.
- ๋ฌผ๋ฆฌ์ ์ผ๋ก ๋์์ ๋๋ ๊ฒ์ด๋ผ ์ฝ์ด๊ฐ ์ฌ๋ฌ ๊ฐ์ฌ์ผ ๊ฐ๋ฅ
๋น์ ๋ก ์ฎ๊ธฐ๋ฉด ์ ๋ช ํ๋ค.
- ๋์์ฑ: ์ผ๊พผ ํ ๋ช ์ด ํด๋ ์ฌ๋ฌ ๊ฐ๋ฅผ ๋ฒ๊ฐ์ ์ฒ๋ฆฌํ๋ค. ํด๋ A๋ฅผ ์กฐ๊ธ ๋ณด๋ค B๋ก, ๋ค์ A๋ก. ์์ด ํ๋๋ผ ๋ฌผ๋ฆฌ์ ๋์ ์คํ์ ์๋์ง๋ง ๋ฐ์์๋ ์ฌ๋ฌ ํด๋๊ฐ ํจ๊ป ์งํ๋๋ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค.
- ๋ณ๋ ฌ์ฑ: ์ผ๊พผ ์ฌ๋ฌ ๋ช ์ด ๊ฐ์ ํด๋๋ฅผ ํ๋์ฉ ์ค์ ๋ก ๋์์ ์ฒ๋ฆฌํ๋ค.
ํ ๋ฌธ์ฅ ๊ตฌ๋ถ
๋์์ฑ์ โ์ฌ๋ฌ ์ผ์ ๋ค๋ฃจ๋ ๊ตฌ์กฐโ์ ๋ฌธ์ ์ด๊ณ , ๋ณ๋ ฌ์ฑ์ โ์ฌ๋ฌ ์ผ์ ๋์์ ํ๋ ์คํโ์ ๋ฌธ์ ๋ค. Rob Pike์ ํํ์ผ๋ก โConcurrency is not parallelism.โ
๋์์ฑ์ ๋ณ๋ ฌ์ฑ์ ์ ์ ๊ฐ ๋ ์ ์๋ค. ์์
์ ์๊ฒ ์ชผ๊ฐ ๋๋ฉด ์ฝ์ด๊ฐ ๋์์ ๋ ๋ณ๋ ฌ๋ก ๋๋ฆด ์ ์๋ค.
๋์ ๊ฐ์ ๋ง์ด ์๋๋ค. ์ฝ์ด ํ๋๋ก๋ ๋์์ฑ์ ๊ฐ๋ฅํ์ง๋ง ๋ณ๋ ฌ์ ๋ถ๊ฐ๋ฅํ๋ค.
7. CPU-bound์ I/O-bound
๋๊ตฌ๋ฅผ ๊ณ ๋ฅด๋ ค๋ฉด ๋จผ์ ์์ ์ด ๋๋ฆฐ ์์ธ์ ๊ตฌ๋ถํด์ผ ํ๋ค.
- CPU-bound: CPU๊ฐ ์ฌ์ง ์๊ณ ๊ณ์ฐํ๋๋ผ ๋๋ฆฐ ์์
.
- ํฐ ๋ฐฐ์ด ์ ๋ ฌ, ์ด๋ฏธ์งยท์์ ๋ณํ, ์ํธํยท์์ถ, ๋จธ์ ๋ฌ๋ ์ ์ฒ๋ฆฌ ๋ฑ
- ๋นจ๋ผ์ง๋ ค๋ฉด ๊ณ์ฐ์ ๋ ๋ง์ ์ฝ์ด์ ๋๋ ์ผ ํจ
- I/O-bound: CPU๋ ๊ฑฐ์ ๋๊ณ ์ธ๋ถ ์์์ ์๋ต์ ๊ธฐ๋ค๋ฆฌ๋๋ผ ๋๋ฆฐ ์์
.
- HTTP ์๋ต ๋๊ธฐ, DB ์ฟผ๋ฆฌ, ํ์ผ ์ฝ๊ธฐ, ์์ผ ๋ฐ์ดํฐ ๋์ฐฉ ๋๊ธฐ ๋ฑ
- ๋นจ๋ผ์ง๋ ค๋ฉด ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ์๋ก ๊ฒน์ณ์ผ ํจ
์ด ๊ตฌ๋ถ์ด ๋๊ตฌ ์ ํ์ ๊ฐ๋ฆผ๊ธธ์ด๋ค.
- ๊ณ์ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๋ฌธ์ (CPU-bound)๋ โ์ด๋ป๊ฒ ์ฌ๋ฌ ์ฝ์ด๋ฅผ ์ธ๊นโ, ๊ณง ๋ณ๋ ฌ์ฑ์ ๋ฌธ์ ๋ค.
- ๋๊ธฐ๊ฐ ์ค๋ ๊ฑธ๋ฆฌ๋ ๋ฌธ์ (I/O-bound)๋ โ๊ธฐ๋ค๋ฆฌ๋ ๋์ ๋ค๋ฅธ ์ผ์ ์ด๋ป๊ฒ ์ํฌ๊นโ, ๊ณง ๋์์ฑ์ ๋ฌธ์ ๋ค.
CPU์ ๋คํธ์ํฌ์ ์๋ ์ฐจ๋ ํฌ๋ค. CPU ์ฐ์ฐ์ ๋คํธ์ํฌ ์๋ณต๋ณด๋ค 10๋ง ๋ฐฐ ์ด์ ๋น ๋ฅด๋ค.
๊ทธ๋์ ๋คํธ์ํฌ I/O๊ฐ ๋ง์ ํ๋ก๊ทธ๋จ์ ์ ์ฒด ์๊ฐ์ ๋๋ถ๋ถ์ ๋๊ธฐ๋ก ํ๋ ค๋ณด๋ด๋ฉฐ, ์ด ๋๊ธฐ๋ฅผ ๊ฒน์น๋ ๊ฒ๋ง์ผ๋ก ์ฒด๊ฐ ์๋๊ฐ ํฌ๊ฒ ์ค๋ฅธ๋ค.
8. ์ง๊ตํ๋ ๋ ์ถ โ synchronous/asynchronous, blocking/non-blocking
7์ ์์ I/O-bound์ ํด๋ฒ์ โ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ์๋ก ๊ฒน์น๋ ๊ฒโ์ด๋ผ ํ๋ค. ๊ทธ๋ฌ๋ ค๋ฉด ํ๋์ ํธ์ถ์ด ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์ด๋ป๊ฒ ํ๋ํ๋์ง๋ถํฐ ์ ๋ฆฌํด์ผ ํ๋ค.
์ฌ๊ธฐ์ ์๋ก ๋ค๋ฅธ ๋ ์ง๋ฌธ์ด ์์ฌ ์๋ค: ๊ธฐ๋ค๋ฆฌ๋ ๋์ ํธ์ถ์์ ํ๋ฆ์ด ๋ฉ์ถ๋, ์๋ฃ๋ฅผ ๋ด๊ฐ ์ฑ๊ธฐ๋ ํต์ง๋ฐ๋.
์์ฃผ ํ ๋ฉ์ด๋ฆฌ๋ก ๋ญ๋ฑ๊ทธ๋ ค์ง์ง๋ง ์ฌ์ค์ ๋
๋ฆฝ๋ ๋ ์ถ์ด๊ณ , ๋ค์ ๋์ฌ event loopยทawaitยทFuture๊ฐ ์ ๋ถ ์ด ์กฐํฉ์ผ๋ก ์ค๋ช
๋๋ค.
synchronous / asynchronous โ โ์๋ฃ๋ฅผ ๋ด๊ฐ ๋ฌป๋, ๋ฐฐ๋ฌ๋๋โ
ํธ์ถ๊ณผ ๊ฒฐ๊ณผ๊ฐ ์๊ฐ์ ์ผ๋ก ๋ฌถ์ฌ ์๋์ง๋ฅผ ๊ฐ๋ฅธ๋ค. ๋ ๋๋ ทํ๊ฒ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ฑ ์์ด ํธ์ถํ ํ๋ฆ์ ์๋๋, ํต์ง ๋ฉ์ปค๋์ฆ์ ๋์ด๊ฐ๋๋์ ๋ฌธ์ ๋ค. ์ฌ๊ธฐ์ โํ๋ฆโ์ OS thread๊ฐ ์๋๋ผ ํธ์ถ ์คํ ํน์ ํธ์ถ์ ์คํํ ์ฝ๋ฃจํด์ ์๋ฏธํ๋ค.
- synchronous: ๊ฒฐ๊ณผ๋ฅผ ํธ์ถํ ํ๋ฆ์ด ์ง์ ์ป๋๋ค (pull).
- ๊ธฐ๋ค๋ ค์ ๋ฐ๋ ๋๋ฌผ์ด์ ๋ฐ๋ , โ๋๋ฌ๋?โ๋ฅผ ํ์ธํ๋ ์ฃผ์ฒด๊ฐ ํธ์ถํ ํ๋ฆ ์์ ์ผ๋ก ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ธฐ ์ ์ ๊ทธ ํ๋ฆ์ด ํธ์ถ ์ง์ ์ ๋ฒ์ด๋์ง ๋ชปํจ
- โ์์ฒญ โ ๊ธฐ๋ค๋ฆผ/ํ์ธ โ ๊ฒฐ๊ณผ ์ฌ์ฉโ์ด ํ ํ๋ฆ์ผ๋ก ์ด์ด์ง
- asynchronous: ํธ์ถํ ํ๋ฆ์ ์์
๋ง ๊ฑธ์ด๋๊ณ ์ ์ด๋ฅผ ๋๋๋ค (hand off).
- ์๋ฃ ํ์ธ์ ํ๋ฆ์ด ์๋๋ผ ๋ฐํ์(event loop ๋ฑ)์ด ๋งก๊ณ , ๋๋๋ฉด ์ฝ๋ฐฑยท์ด๋ฒคํธยท
await์ฌ๊ฐ๋ก ๊ฒฐ๊ณผ๊ฐ ๋ฐฐ๋ฌ๋๋ค(push) - ๋ด๊ฐ ๋ค์ ๋ฌป์ง ์์๋ ํต์ง๊ฐ ์ค๊ณ (
await, ์ฝ๋ฐฑ,Future.result()๋ฑ), โ์์ ์์โ๊ณผ โ๊ฒฐ๊ณผ ์๋นโ๊ฐ ๋ถ๋ฆฌ๋๋ค
- ์๋ฃ ํ์ธ์ ํ๋ฆ์ด ์๋๋ผ ๋ฐํ์(event loop ๋ฑ)์ด ๋งก๊ณ , ๋๋๋ฉด ์ฝ๋ฐฑยท์ด๋ฒคํธยท
์๋น์ผ๋ก ์น๋ฉด synchronous๋ ์นด์ดํฐ์ ์์ ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋(blocking) 10์ด๋ง๋ค โ๋์ด์?โ๋ฅผ ๋๋ฌป๋ ๊ฒ(non-blocking)์ด๊ณ ,
asynchronous๋ ์ง๋๋ฒจ์ ๋ฐ์ ์๋ฆฌ์์ ๋ด ์ผ์ ํ๋ค ๋ฒจ์ด ์ธ๋ฆฌ๋ฉด ๋ฐ์ผ๋ฌ ๊ฐ๋ ๊ฒ์ด๋ค. ์ด ์ง๋๋ฒจ์ด ์ฝ๋ฐฑยท์ด๋ฒคํธ ํต์ง์ด๋ฉฐ, ๋ด๊ฐ ์ ๋ฌผ์ด๋ด๋ ์ ์ชฝ์ด ์๋ ค์ค๋ค๋ ๊ฒ asynchronous์ ๋ณธ์ง์ด๋ค.
์ด ์ง๋๋ฒจ์ ๊ฐ์ฒด๋ก ๋ง๋ ๊ฒ์ด Future๋ค(์ธ์ด์ ๋ฐ๋ผ Promise).
async ํธ์ถ์ ๊ฒฐ๊ณผ ๋์ ๋น ์์(Future)๋ฅผ ์ฆ์ ๋๋ ค์ฃผ๊ณ , ์์
์ด ๋๋๋ฉด ๊ทธ ์์๊ฐ ์ฑ์์ง๋ค. future.result()๋ก ๋ด๊ฐ ๊ฐ์ ๋ถ๋ฅด๋ฉด pull(์์ง์ด๋ฉด ๊ทธ ์๋ฆฌ์ blocking์ผ๋ก ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ asyncio์ ๊ฒฝ์ฐ exception์ ๋์ง), await๋ ์๋ฃ ์ฝ๋ฐฑ์ผ๋ก ํต์ง๋ฐ์ผ๋ฉด push๋ค.
Future ์์ฒด๋ ๊ฒฐ๊ณผ๊ฐ ๋ด๊ธธ ์๋ฆฌ์ผ ๋ฟ์ด๊ณ , ์ค์ ์์
์ Executor(์ค๋ ๋ํยทํ๋ก์ธ์คํ)๋ event loop๊ฐ ์ํํด ์ฑ์ด๋ค.
(awaitยทevent loop์ ๋์์ 9์ , Executor๋ 16์ ์์ ์ด์ด์ง)
๋จ, ์ด ๊ตฌ๋ถ์ ๊ฒฐ๊ณผ๊ฐ ์ด ์ค๋ ๋ ๋ฐ์์ ๋์ค๋ ํธ์ถ์์๋ง ์๋ฏธ๊ฐ ์์ผ๋ฉฐ ์ด๋ I/O(๋คํธ์ํฌยทํ์ผยทDBยทํ์ด๋จธ)๊ฐ ์ด์ ํด๋นํ๋ค.
์์ ๊ณ์ฐ ํจ์(compute(x) ๊ฐ์ ๋ก์ปฌ ํธ์ถ)๋ ์ด ์ค๋ ๋๊ฐ ์๊ธฐ CPU๋ก ์ง์ ์คํํ๋ โ๋์ค์ ๋ฐ๋๋คโ๋ ์ ํ์ง๊ฐ ์์ด ์ธ์ ๋ synchronous๋ค. ๊ณ์ฐ์ async๋ก ๋๋ฆฌ๋ ค๋ฉด ๋ค๋ฅธ ์ค๋ ๋ยทํ๋ก์ธ์ค์ ์์ํด์ผ ํ๊ณ , ๊ทธ ์๊ฐ ๊ทธ ํธ์ถ์ ์ด๋ฏธ I/O์ฒ๋ผ โ๋งก๊ธฐ๊ณ ๋์ค์ ํ์โํ๋ ๊ตฌ์กฐ๊ฐ ๋๋ค.
blocking / non-blocking โ โ๊ธฐ๋ค๋ฆฌ๋ ๋์ ํธ์ถ์์ ํ๋ฆ์ด ๋ฉ์ถ๋โ
์ ์ด๊ถ์ ์งํ ์ฌ๋ถ๋ฅผ ๊ฐ๋ฅธ๋ค. ์ด ์ถ์ ์์ ์ธ๊ธํ๋ thread์ ์ํ๋ก ๊ณง์ฅ ๋์๋๋ค.
- blocking: ์์
์ด ๋๋ ๋๊น์ง ํ์ฌ ์คํ ํ๋ฆ์ด ๋ฉ์ถค
- ์ ํํ๋ โํ์ํ๋ฉด ๊ธฐ๋ค๋ฆด ์ํฅโ์ด๋ผ, ์ค์ ๋ก ๊ธฐ๋ค๋ ค์ผ ํ ๋ kernel์ด ๊ทธ thread๋ฅผ ์ฌ์ Blocked๋ก ๋ณด๋
- ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ์ค๋น๋ผ ์์ผ๋ฉด blocking ํธ์ถ๋ ์ ์๊ณ ๋ฐ๋ก ๋์์ด
- non-blocking: ์ง๊ธ ๋น์ฅ ๋๋ผ ์ ์์ผ๋ฉด ์ฆ์ ์ ์ด๊ถ์ ๋๋ ค์ค
- thread๋ ๋ฉ์ถ์ง ์๊ณ Running/Runnable์ ์ ์งํ๋ฉฐ, ๊ฒฐ๊ณผ๋ ๋์ค์ ๋ค์ ํ์ธํ๊ฑฐ๋ ํต์ง๋ฐ๋๋ค.
sync/async๊ฐ ํท๊ฐ๋ฆฌ๋ ์ด์
blocking/non-blocking์ thread์ CPU ์ํ, ์ฆ Running์ด๋ Blocked๋๋ก ๊ทธ๋๋ก ๋งคํ๋๋ machine ๋์ ์์ฒด๋ผ ์ง๊ด์ ์ด๋ค.
๋ฐ๋ฉด synchronous/asynchronous๋ ๋์๋๋ CPU ์ํ๊ฐ ์๋ค.
ํ๋์จ์ด ์ํ๊ฐ ์๋๋ผ โ์๋ฃ๋ฅผ pull ํ๋๋ push ๋ฐ๋๋โ๋ ์ ์ด ํ๋ฆ์ ๊ณ์ฝ์ด๋ผ ํ ๋จ๊ณ ๋ ์ถ์์ ์ด๋ค.๋ ํ๋์ ํจ์ ์ โํ์ธํ๋ ์ฃผ์ฒดโ๋ฅผ thread๋ก ์คํดํ๋ ๊ฒ์ด๋ค. ๋จ์ผ thread
asyncio์์ ์๋ฃ๋ฅผ ํ์ธํ๋ event loop๋ ๊ฒฐ๊ตญ ๊ฐ์ thread์์ ๋๋ค. ๋ฌผ๋ฆฌ์ thread๋ ๊ฐ์๋ ๋ ผ๋ฆฌ์ ์ผ๋ก ํ์ธํ๋ ํ๋ฆ์ด ๋ค๋ฅด๋ค: synchronous๋ ํธ์ถํ ์ฝ๋ฃจํด ์์ ์ด, asynchronous๋ event loop์ด ํ์ธํ๋ค. ๊ทธ๋์ ์ด ์ถ์ โ์ด๋ thread๊ฐ ์ฒ๋ฆฌํ๋โ๊ฐ ์๋๋ผ โํธ์ถํ ํ๋ฆ์ด ๊ฒฐ๊ณผ ํ์ธ์ ๋งค์ฌ ์๋โ๋ก ๋ด์ผ ํ๋ค.๋์ด ์๋ก ๋ค๋ฅธ ์ธต์์ ์ง๋ฌธ์ด๋ผ ์ง๊ตํ๊ณ , ๊ทธ๋์ ์กฐํฉ์ด ๋ท ๋์จ๋ค.
๋ ์ถ์ 2ร2๋ก ๋ณด๋ฉด
| blocking | non-blocking | |
|---|---|---|
| synchronous | ๊ฐ์ฅ ํํจ. requests.get(), ๊ธฐ๋ณธ ์์ผ recv(), time.sleep() | ์ ์์ค์์ ๊ฐ๋ฅ. non-blocking ์์ผ์ recv()๋ก ์ฆ์ ํ์ธ |
| asynchronous | ๊ฑฐ์ ์์(์ฌ์ค์ ์ํฐํจํด) | asyncio์ ์ด์ํ. await๋ก ๋ฑ๋กํ๊ณ ์ฆ์ ์๋ณด, ๊ฒฐ๊ณผ๋ ๋์ค์ |
- sync + blocking: ๊ฒฐ๊ณผ๋ฅผ ์ง์ ๊ธฐ๋ค๋ฆฌ๊ณ , ๋์ฌ ๋๊น์ง thread๊ฐ Blocked๋ก ์ ๋ ๋ค. ๊ฐ์ฅ ํํ ํํ๋ค.
- sync + non-blocking: ๊ฒฐ๊ณผ๋ฅผ ์ง์ ํ์ธํ๋ ์์ง์ด๋ฉด ์ฆ์ ๋์์ค๊ณ , ์ค๋น๋ ๋๊น์ง ๋๋ฌป๋๋ค(polling). thread๋ Running์ ์ ์งํ๋ค.
- async + blocking: ํต์ง๋ฅผ ๋ฑ๋กํด ๋๊ณ ๊ทธ ํต์ง๋ฅผ ๋ค์ blocking์ผ๋ก ๊ธฐ๋ค๋ฆฌ๋ ๊ผด์ด๋ผ ๋ ๋ฐฉ์์ ์ด์ ์ด ์์๋๋ ์ํฐํจํด์ด๋ค.
- async + non-blocking: ๋ฑ๋กํ๊ณ ์ฆ์ ์๋ณดํ ๋ค ๊ฒฐ๊ณผ๋ ๋์ค์ ํต์ง๋ฐ๋๋ค.
asyncio์ ์ด์ํ์ด๋ค.
์ฌ๊ธฐ์ ํํ ์๊ธฐ๋ ๋ํ์ ์ธ ์คํด๋ค์ ์ง๊ณ ๋์ด๊ฐ์
- โasynchronous = ๋น ๋ฆโ์ด ์๋๋ค.
- asynchronous๋ ํ๋ฆ ์ ์ด ๋ฐฉ์์ผ ๋ฟ์ด๋ค.
- โsynchronous = CPU๋ฅผ ์ค๋ ์ด๋คโ๋ ์๋๋ค.
- synchronous ํธ์ถ๋ ๋๋ถ๋ถ์ ์๊ฐ์ ๋๊ธฐ๋ก ๋ณด๋ผ ์ ์๋ค.
- blocking I/O ์ค์๋ ๊ทธ thread๊ฐ Blocked๋ก ๊ฐ๊ณ ์ฝ์ด๋ ๋ค๋ฅธ thread๊ฐ ์ด๋ค(4์ ).
- synchronous + non-blocking์ ๊ฐ๋ฅํ๋ค.
- non-blocking ์์ผ์
while True: recv()๋ก ๊ณ์ ํ์ธํ๋ ๋ฐฉ์์ธ๋ฐ, ์ด๋ฌ๋ฉด CPU๋ฅผ ํ์ฐ๋ busy polling์ด ๋๋ค. - ๊ทธ๋์ ๋ณดํต์ OS์ ๊ฐ์ ๊ธฐ๋ฅ(
selectยทepoll)์ผ๋ก ์ค๋น๋ ์์๋ง ํ์ธํ๋ค(11์ ). - ๋ค๋ง ์ ์ง์ฐ์ด ๊ด๊ฑด์ธ ์์คํ (๊ณ ๋น๋ ํธ๋ ์ด๋ฉ, ์ปค๋ ์ฐํ ํจํท ์ฒ๋ฆฌ)์์๋ thread๋ฅผ ์ฌ์ ๋ค ๊นจ์ฐ๋ ์ง์ฐ์กฐ์ฐจ ์๊น์, ์ด busy polling์ ์ผ๋ถ๋ฌ ์ฐ๊ธฐ๋ ํ๋ค.
- non-blocking ์์ผ์
9. ๋ ๊ฐ๋ โ preemptive์ cooperative
์ด์ ์ด ํ ๋ ์์์ ๊ตฌํ๋ ๋์์ฑ์ ํฌ๊ฒ ๋ ๊ฐ๋์ด๊ณ , ์ ํ์ด ๋๊ฐยท์ธ์ ยท์ผ๋ง๋ ๋น์ธ๊ฒ ์ผ์ด๋๋์ง์์ ๊ฐ๋ฆฐ๋ค.
ํ๋๋ kernel์ด ๊ฐ์ ๋ก ํ๋ฆ์ ๋ฐ๊พธ๋ preemptive, ๋ค๋ฅธ ํ๋๋ ์ฝ๋๊ฐ ์ค์ค๋ก ์คํ๊ถ์ ๋๊ธฐ๋ cooperative๋ค.
(A) OS thread ๊ฐ ์ ํ โ preemptive
5์ ์์ ๋ณธ ๋๋ก kernel์ด ๊ฐ์ ๋ก context switch ํ๋ค.
์ฝ๋๋ ํ๋ฒํ synchronous ๋ฐฉ์์ผ๋ก ์ง๊ณ , OS๊ฐ ์์์ ๋ฒ๊ฐ์ ๋๋ฆฐ๋ค. thread๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๊ณ , process๋ ๊ฒฉ๋ฆฌ๋๋ค.
- ์ ํ์ ์ฃผ์ฒด: kernel(๊ฐ์ , ์ฝ๋๋ ์์ง ๋ชปํจ)
- ๋น์ฉ: ํผ(kernel ๊ฒฝ์ + ์บ์ ์ํฅ)
- ๋ณ๋ ฌ: ๊ฐ๋ฅ(์ฌ๋ฌ ์ฝ์ด์ ์ค์ ๋ก ๋ฐฐ์น)
- ์ํ: ๊ณต์ ๋ฉ๋ชจ๋ฆฌ thread์ race condition, ์ ํ ๋น์ฉ
(B) coroutine ๊ฐ ์ ํ โ cooperative
ํ๋์ OS thread ์์์ ์ฌ๋ฌ coroutine์ด ๋์๊ฐ ๋, ๊ทธ ์์์ event loop๊ฐ ๋ฌดํ ๋ฃจํ๋ฅผ ๋๋ฉฐ ์คํํ ์ ์๋ coroutine์ ๊ณจ๋ผ ๋๋ฆฐ๋ค.
ํ coroutine์ด await๋ก ๋๊ธฐ์ ๋ค์ด๊ฐ๋ฉด event loop๋ ๊ทธ๊ฒ์ ์ ์ณ๋๊ณ ๋ค์ coroutine์ผ๋ก ๋์ด๊ฐ๋ฉฐ, ๋๊ธฐ๊ฐ ๋๋๋ฉด ๋ฉ์ท๋ ์ง์ ๋ถํฐ ์ฌ๊ฐํ๋ค.
์ฝ๋๊ฐ await์์ ์ค์ค๋ก ์คํ๊ถ์ ๋๊ธฐ๋ฏ๋ก ์ด ๋ฐฉ์์ cooperative multitasking์ด๋ผ ํ๋ค. kernel์ ๊ฑฐ์น์ง ์๋ ์ ์ ๊ณต๊ฐ ์ ํ์ด๋ผ ๋น์ฉ์ด ์๋ค.
๋น์ ๋ก ์ฎ๊ธฐ๋ฉด, ์ด๊ฑด ์๊ฑด์ด ์๋ฉ ๋ ํด๋ ํ๋๋ค. ์ผ๊พผ์ ์(๋
ผ๋ฆฌ ์ฝ์ด)์ด ํ๋๋ฟ์ธ ์ด ํด๋๋ฅผ ์ก๊ณ , ๊ทธ ์ ์๊ฑด(coroutine)๋ค์ ๋ฒ๊ฐ์ ์ฒ๋ฆฌํ๋ค.
ํ ์๊ฑด์ด โ์ธ๋ถ ๋ต๋ณ ๋๊ธฐโ(await)์ ๊ฑธ๋ฆฌ๋ฉด ์์ฒด ๋ถ๋งํฌ๋ฅผ ๋จ๊ธฐ๊ณ ๊ฐ์ ํด๋์ ๋ค์ ์๊ฑด์ผ๋ก ๋์ด๊ฐ๋ค. ํด๋๊ฐ ํ๋๋ผ ์์ด ์ด ๊ฐ์ฌ๋ ํ ์๋ง ์ด ํด๋๋ฅผ ์ก์ ์ ์์ด ๋ณ๋ ฌ์ ๋์ง ์๋๋ค. ๋์ ์๊ฑด๋ค์ ๋๊ธฐ ์๊ฐ์ด ์๋ก ๊ฒน์ณ์ง๋ ์ผ๊พผ์ด ๋
ธ๋ ์๊ฐ ์์ด ์ฌ๋ฌ ์๊ฑด์ ๋ฐ์ด๋ถ์ธ๋ค.
event loop์ ์คํ ๋จ์๊ฐ ์๋๋ผ "์ค์ผ์ค๋ฌ ๊ฐ์ฒด"๋ค
processยทthreadยทcoroutine์ด ๊ฐ์ ์คํ ์ํ๋ฅผ ๋ด์ ์คํ ๋จ์๋ผ๋ฉด, event loop์ ๊ทธ๊ฒ๋ค์ ๊ณ ๋ฅด๊ณ ๊ตด๋ฆฌ๋ ๊ตฌ๋๊ธฐ๋ค.
์ถ์ ๊ฐ๋ ๋ง์ด ์๋๋ผ ๊ตฌํ์์ ์คํ ์ค๋น๋ ๊ฒ๋ค์ ๋ด์ ๋๊ณ ํ๋์ฉ ๊บผ๋ด ๋๋ฆฌ๋ ๊ตฌ์ฒด์ ๊ฐ์ฒด์ด๋ฉฐ ๊ทธ๊ฒ์ด ๋ โ๋ฉ๋ชจ๋ฆฌโ๋ ์คํ ์ปจํ ์คํธ๊ฐ ์๋๋ผ ๋ฌด์์ ๋ค์์ ๋๋ฆด์ง ์ ์ ๊ด๋ฆฌ์์ ์ฅ๋ถ๋ค.๊ด๋ฆฌ์ ์ญํ ์ kernel์ด ์๋๋ผ user space์์ ๋งก๋ ์ ์ด๋ฉฐ, ๊ทธ ๋ด๋ถ ์๋ฃ๊ตฌ์กฐ์ ํ ๋ฐํด์ ๋์์ 11์ ์์ ์์ธํ ๋ณธ๋ค.
- ์ ํ์ ์ฃผ์ฒด: ์ฝ๋ ์์ (
await์ง์ ์์ ์๋ฐ์ ์ผ๋ก) - ๋น์ฉ: ์์(์ ์ ๊ณต๊ฐ, kernel ๊ฑฐ์น์ง ์์)
- ๋ณ๋ ฌ: ๋ถ๊ฐ๋ฅ(๋จ์ผ thread๋ผ ๋งค ์๊ฐ ํ๋๋ง ์คํ)
- ์ฅ์ : ์ ํ ์ง์ ์ด ์ฝ๋์
await๋ก ๋๋ฌ๋ ์ถ์ ํ๊ธฐ ์ฌ์ - ํจ์ : ํ coroutine์ด ์๋ณดํ์ง ์๊ณ ์ค๋ ๋ถ์ก์ผ๋ฉด event loop ์ ์ฒด๊ฐ ๋ฉ์ถค
coroutine์ด ๊ฐ๋ฒผ์ด ์ด์
์ผ๋ฐ ํจ์๋ ํธ์ถ๋๋ฉด ์คํ ํ๋ ์์ด ์์ด๊ณ ๋๋๋ฉด ์ฌ๋ผ์ง๋ค. ์ค๊ฐ์ ๋ฉ์ท๋ค ์ฌ๊ฐํ๊ธฐ ์ด๋ ต๋ค.
coroutine์ โ์ด๋๊น์ง ์คํํ๋์ง, ๋ค์์ ์ด๋์ ์ฌ๊ฐํ ์ง, ์ง์ญ ์ํ๊ฐ ๋ฌด์์ธ์งโ๋ฅผ ๊ฐ์ฒด ํํ์ ๊ฐ๋ฒผ์ด ์คํ ์ํ๋ก ๋ค๊ณ ๋ค๋๋ค.
๋๋ถ์ OS thread๋ณด๋ค ํจ์ฌ ๋ง์ ์๋ฅผ ๋์ธ ์ ์๋ค. thread๊ฐ ๊ฐ์ ํฐ ์คํ์ ๋ฏธ๋ฆฌ ์ก์๋๋ ๊ฒ๊ณผ ๋๋น๋๋ค.
โasynchronous ์ฒ๋ฆฌ๊ฐ OS์ context switch์ ๋ฌด์์ด ๋ค๋ฅธ๊ฐโ๋ผ๋ ์ง๋ฌธ์ ๋ต์ด ์ (A)ยท(B)์ ๋๋น์ ์๋ค.
OS thread์ ์ ํ์ kernel์ด ๊ฐ์ ํ๋ ๋ฌด๊ฑฐ์ด ์ ํ์ด๊ณ , event loop์ ์ ํ์ ์ฝ๋๊ฐ await์์ ์๋ฐ์ ์ผ๋ก ํ๋ ๊ฐ๋ฒผ์ด ์ ํ์ด๋ค.
๊ฐ์ โ์ ํโ์ด๋ผ๋ ๋จ์ด๋ฅผ ์ฐ์ง๋ง ์ฃผ์ฒด์ ์์ , ๋น์ฉ์ด ๋ค๋ฅด๋ค. ์ฌ๊ธฐ์ goroutine๊น์ง ๋ํ ์ธ ๋ชจ๋ธ ๋น๊ต๋ ๋ค์ ์ ๋ ํ์ ์๋ค.
10. ์ 3์ ๊ธธ โ M:N runtime๊ณผ goroutine
์์ ๋ ๋ชจ๋ธ์ ๊ฐ๊ฐ ๋๊ฐ๊ฐ ์๋ค.
- OS thread๋ ์ง์ง ๋ณ๋ ฌ์ ์ค ์ ์์ง๋ง ์ ํ์ด ๋ฌด๊ฒ๊ณ , ์๊ฐ ๋ง์์ง๋ฉด ๋ถ๋ด์ด ์ปค์ง๋ค.
- event loop๋ ๊ฐ๋ณ์ง๋ง ๋จ์ผ thread๋ผ ๋ณ๋ ฌ์ด ๋์ง ์๋๋ค.
์ด ๋์ ์ฅ์ , ๊ณง preemptive์ ๋ณ๋ ฌ๊ณผ cooperative์ ๊ฐ๋ฒผ์์ ํฉ์น๋ ค๋ ๊ฒ์ด ์ธ์ด ๋ฐํ์์ด ์คํ ํ๋ฆ์ ์ง์ ๊ด๋ฆฌํ๋ M:N ๋ชจ๋ธ์ด๋ค.
user thread๋ฅผ OS thread์ ๋ช ๋ ๋ช์ผ๋ก ์น๋๋๊ฐ threading model์ ๊ฐ๋ฅธ๋ค.
- 1:1: user thread ํ๋์ OS thread ํ๋
- Python
threading, ๋ฆฌ๋ ์คpthread๊ฐ ์ด ๋ฐฉ์์ด๋ผ ๋์ ๊ตฌ๋ถ์ด ์ ๋๋ฌ๋์ง ์๋๋ค.
- Python
- N:1: ์ฌ๋ฌ user thread๋ฅผ OS thread ํ๋์
- event loop์ coroutine๋ค์ด ํด๋น
- kernel์ด ํ๋๋ก๋ง ์ธ์ํ๊ธฐ ๋๋ฌธ์ ๋ณ๋ ฌ์ด ์ ๋๋ค.
- M:N: ์ฌ๋ฌ user thread๋ฅผ ์ฌ๋ฌ OS thread์
- ๋ณ๋ ฌ์ด ๋๋ฉฐ, ์๋ goroutine์ด ๋ํ์ ์ธ ์์
Go์ goroutine์ด ๊ทธ M:N์ ๋ํ ์ฌ๋ก๋ค.
์๋ง์ goroutine์ ์ ์ ์์ OS thread ์์ Go ๋ฐํ์์ด ๋งคํํด ๋๋ฆฐ๋ค. goroutine์ด ์ฑ๋ยทI/Oยท์์คํ
์ฝ์์ ๋งํ๋ฉด ๋ฐํ์์ด ๊ทธ goroutine์ ๋นผ๋๊ณ ๊ฐ์ OS thread์ ๋ค๋ฅธ goroutine์ ์ฌ๋ฆฐ๋ค.
์ด ์ ํ๋ ์ ์ ๊ณต๊ฐ์์ ์ผ์ด๋ ๋น์ฉ์ด ์๊ณ ๋ฐํ์์ ์ฌ๋ฌ OS thread๋ฅผ ๋์์ ์ฐ๋ฏ๋ก ์ง์ง ๋ณ๋ ฌ๋ ๊ฐ๋ฅํ๋ค.
- ์ ํ์ ์ฃผ์ฒด: ์ธ์ด ๋ฐํ์(๋งํ๋ ์ง์ + ๋ฐํ์์ ์ ์ )
- ๋น์ฉ: ์์(์ ์ ๊ณต๊ฐ)
- ๋ณ๋ ฌ: ๊ฐ๋ฅ(์ฌ๋ฌ OS thread์ ๋ถ์ฐ)
- ํ ์ค ์์ฝ: preemptive์ ์ง์ง ๋ณ๋ ฌ๊ณผ cooperative์ ๊ฐ๋ฒผ์์ ํฉ์น ์๋ฆฌ
์ด ๋ฐ์์ Go๋ง์ ๊ฒ์ด ์๋๋ค.
Java์ virtual thread(Project Loom), ErlangยทElixir์ ๊ฒฝ๋ process๋ ๋ฐํ์์ด ๊ฒฝ๋ ์คํ ํ๋ฆ์ ์์์ OS thread์ ์ค์ด ๋๋ฅด๋ ๊ฐ์ ๊ฐ๋๋ค.
threading model ๋น๊ต
| ๋ชจ๋ธ | ๋๊ฐ ์ ํํ๋ | ์ธ์ | ๋น์ฉ | ์ง์ง ๋ณ๋ ฌ? | ์ฝ๋ ๋ชจ์ต |
|---|---|---|---|---|---|
| OS thread (preemptive) | kernel์ด ๊ฐ์ ๋ก | OS๊ฐ ์์ ์์ ์ | ํผ(kernel) | O | ํ๋ฒํ synchronous ์ฝ๋ |
| coroutine (cooperative) | ์ฝ๋๊ฐ ์ค์ค๋ก | await ์ง์ ์์ | ์์(์ ์ ) | X (๋จ์ผ thread) | async/await ํ์ |
| goroutine (M:N) | ๋ฐํ์์ด | ๋งํ๋ ์ง์ + ์ ์ | ์์(์ ์ ) | O | ํ๋ฒํ synchronous ์ฝ๋ |
11. ๋น๋๊ธฐ I/O์ ์ค์ ๋์
๋จ์ผ thread event loop๊ฐ ์์ฒ ๊ฐ์ ์์ผ์ ๋์์ ๋ค๋ฃฐ ์ ์๋ ๊ฑด OS์ O multiplexing ๋๋ถ์ด๋ค. ์๋ฆฌ๋ ๋จ์ํ๋ค.
- ์์ฒ ๊ฐ์ ์์ผ์ ์ผ์ผ์ด blocking์ผ๋ก ํ๋์ฉ ๊ธฐ๋ค๋ฆฌ๋ ๋์ ,
epoll_wait์ผ๋ก OS์ โ์ด ์ค ์ค๋น๋ fd๋ง ์๋ ค๋ฌ๋ผโ๊ณ ๋งก๊ธด๋ค.
์ด ํต์ง๋ฅผ ๋ฐ์ ์ค๋น๋ ๊ฒ๋ง ๊ณจ๋ผ ์ฒ๋ฆฌํ๋ ๊ฒ event loop์ด๋ค. 9์ ์์ โ์ค์ผ์ค๋ฌ ๊ฐ์ฒดโ๋ผ ๋ถ๋ฅธ ๊ทธ ๋ด๋ถ๋ฅผ ๋ฏ์ด๋ณด์.
์ธ ์๋ฃ๊ตฌ์กฐ์ ์ ๋ ฅ์
๋จผ์ ์ฉ์ด๋ฅผ ๋ง์ถ์. ์ธ ๊ตฌ์กฐ์ ๋ด๊ธฐ๋ ๊ฑด coroutine ์์ฒด๊ฐ ์๋๋ผ ์ฝ๋ฐฑ(asyncio ๋ด๋ถ์์ Handle)์ด๋ค. ์ด ์ฝ๋ฐฑ์ ์คํํ๋ฉด ๋ฌถ์ธ coroutine์ด ๋ค์ await๊น์ง ์ฌ๊ฐ๋๋ค.
ํธ์์ โcoroutine์ด ํํน๋๋คโ๊ณ ๋งํ์ง๋ง, ์ค์ ๋ก ๋ ๊ฑด ๊ทธ ์ฌ๊ฐ ์ฝ๋ฐฑ ๊ณง continuation์ด๋ค.
event loop์ ์ด ์ฝ๋ฐฑ๋ค์ ์ธ ์๋ฃ๊ตฌ์กฐ์ ๋๋ ๋ด๋๋ค. ์ฝ๋ฐฑ์ด โ์ธ์ ์คํ๋ผ์ผ ํ๋โ๋ก ๊ฐ๋ฆฐ๋ค.
- ready ํ: ์ง๊ธ ๋น์ฅ ์คํํ ์ฝ๋ฐฑ์ ๋๊ธฐ์ด (์ฆ์ ์คํ)
- timer heap: ์๊ฐ์์ผ๋ก ์ ๋ ฌ๋ ์์ฝ. ๋งจ ์์ด ๊ฐ์ฅ ์ด๋ฅธ ์์ฝ (์๊ฐ ๋๋)
- selector:
epoll์ ๊ฐ์ผ ๋ํผ. โ์ด๋ค fd๋ฅผ ๊ฐ์ ์ค์ด๊ณ ์ค๋น๋๋ฉด ์ด๋ค ์ฝ๋ฐฑ์ ๊นจ์ฐ๋โ์ ๋งคํ์ ๋ ๋ค (fd ์ค๋น)
์ฝ๋ฐฑ์ด ์ด ์ธ ๊ตฌ์กฐ์ ์ฒ์ ๋ค์ด๊ฐ๋ primitive ๊ฒฝ๋ก๋ ์ ๋ฟ์ด๊ณ , ๋๋จธ์ง API๋ ์ ๋ถ ๊ทธ ์์ ์นํ ์๋ค.
| primitive | ์ฒ์ ๋์ด๋ ๊ณณ | ready ํ๋ก ๋ค์ด๊ฐ๋ ๊ณ๊ธฐ |
|---|---|---|
loop.call_soon(cb) | ready ํ ์งํ | ์ฆ์. ๋ค์ ๋ฐํด์ ์คํ |
loop.call_later(d, cb) ยท call_at | timer heap | ๊ทธ ์๊ฐ์ด ์ง๋๋ฉด ์ด๋ |
loop.add_reader/add_writer(fd, cb) | selector | epoll์ด ๊ทธ fd ์ค๋น๋ฅผ ์๋ฆฌ๋ฉด ์ด๋ |
ready ํ๋ก ์งํํ๋ ๊ฑด call_soon๋ฟ์ด๋ค.
timer heap๊ณผ selector๋ ๋๊ธฐ์๋ผ, ๊ฑฐ๊ธฐ ๋ ์ฝ๋ฐฑ์ โ์๊ฐ ๋๋โ๋ โfd ์ค๋นโ๋ผ๋ ๊ณ๊ธฐ๊ฐ ์์ด์ผ ready ํ๋ก ์ฎ๊ฒจ์ง๋ค.
์์ API๋ ์ ๋ถ ์ด ์ ์ผ๋ก ํ์๋๋ค.
asyncio.create_task(coro)โ ์ฒซ ์คํ ์call_soonโ ready ํ ์งํ- Future ์๋ฃ(
set_result/set_exception) โ ๊ฑธ๋ฆฐ done ์ฝ๋ฐฑ์call_soon์ผ๋ก โ ready ํ asyncio.sleep(d)โcall_laterโ timer heapawait sock.recv()ยทreader.read()ยทwriter.drain()โadd_reader/add_writerโ selectorasyncio.wait_for(coro, t)ยทtimeout(t)โ I/O๋ selector, ๋ฐ๋๋ผ์ธ์ timer heap์ ๋ ๋คcall_soon_threadsafe(cb)ยทrun_in_executor๊ฒฐ๊ณผ โ ํ ์ค๋ ๋๊ฐ ready ํ์ ๋ฃ๊ณepoll_wait์ ๊นจ์
call_soonยทcall_later์ loop์ ๋ฉ์๋
asyncio.call_soon๊ฐ์ ๋ชจ๋ ํจ์๊ฐ ์๋๋ผloop.call_soon(cb)๊ผด๋ก loop ๊ฐ์ฒด์ ๋ถ์ด ์๊ณ , coroutine์ด ์๋๋ผ ํ๋ฒํ ์ฝ๋ฐฑ์ ๋ฐ๋๋ค. ์ง์ ๋ถ๋ฅผ ์ผ์ ๋๋ฌผ๊ณsleepยทtimeoutยทcreate_task๊ฐ ๋ด๋ถ์์ ๋ถ๋ฅธ๋ค.
event loop ํ ๋ฐํด๊ฐ ํ๋ ์ผ
event loop์ ์ด๋ฆ ๊ทธ๋๋ก ํ๋์ OS thread ์์์ while ๋ฌดํ ๋ฃจํ๋ฅผ ๋๋ค. ํ ๋ฐํด๋ ๋๋ต ์ด๋ ๋ค.
- timer heap ๋งจ ์์ ๋ณด๊ณ ๋ค์ ์์ฝ๊น์ง ๋จ์ ์๊ฐ์ ๊ณ์ฐํ๋ค. ์ด๊ฒ ๋ค์ ๋จ๊ณ์ ์ ํ ์๊ฐ์ด ๋๋ค.
- ๊ทธ ์๊ฐ์ ์ ํ์ผ๋ก selector๋ฅผ ๊ฒฝ์ ํด
epoll_wait์ ๋ถ๋ฅธ๋ค.- ๊ฐ์ ์ค์ธ fd๊ฐ ์ค๋น๋๋ฉด ์ฆ์ ๊นจ๊ณ , ์๋ฌด๊ฒ๋ ์์ผ๋ฉด timer ์๊ฐ๊น์ง ์๋ค โ loop์ด ์ ์ผํ๊ฒ blocking๋๋ ์ง์
- ready ํ์ ์ด๋ฏธ ์ฝ๋ฐฑ์ด ์์ผ๋ฉด ๋๊ธฐ ์์ด ์ง๋๊ฐ๋ค
- ๊นจ์ด๋๋ฉด selector์ ์ค๋น๋ fd ์ฝ๋ฐฑ๊ณผ timer heap์ ๋ง๋ฃ๋ ์ฝ๋ฐฑ์ ready ํ๋ก ์ฎ๊ธด๋ค.
call_soon์ผ๋ก ์ด๋ฏธ ๋ค์ด์ ์๋ ์ฝ๋ฐฑ๊น์ง, ์ด ์ ์ด ์ด๋ฒ ๋ฐํด์ ์คํํ ๋ชฉ๋ก์ด๋ค. - ์ด๋ฒ ๋ฐํด ์์ ์์ ์ ํ์ ์๋ ์ฝ๋ฐฑ์ ํ๋์ฉ ์คํํ๋ค. ๊ฐ ์ฝ๋ฐฑ์ด ๋ฌถ์ธ coroutine์ ๋ค์
await๊น์ง ๊ตด๋ฆฌ๊ณ , ์คํ ์ค ์๋ก ๊ฑธ๋ฆฐ ์ฝ๋ฐฑ์ ๋ค์ ๋ฐํด๋ก ๋๊ธด ๋ค 1๋ก ๋์๊ฐ๋ค.
๋์ฌ๊ฒจ๋ณผ ์ ์ timer์ I/O๊ฐ ํ ๋ฒ์ epoll_wait์ผ๋ก ํตํฉ๋๋ค๋ ๊ฒ์ด๋ค. fd๊ฐ ํ๋๋ ์ค๋น ์ ๋ผ๋ ๋ค์ timer ์๊ฐ์ ๊นจ์ผ ํ๋ฏ๋ก, loop์ โ๋ค์ ์์ฝ๊น์งโ๋ฅผ ์ ํ ์๊ฐ์ผ๋ก ๋๊ฒจ ๋ ์ด๋ฒคํธ์์ ํ ๋๊ธฐ๋ก ํฉ์น๋ค.
%%{init: {'flowchart': {'curve': 'linear'}}}%% flowchart LR CL(["call_later ยท ์ง์ฐ ์์ฝ"]) AR(["add_reader/writer ยท fd ๋ฑ๋ก"]) CS(["call_soon ยท ์ฆ์ ์์ฝ"]) subgraph EL["event loop"] direction TB TH["timer heap"] SEL["selector = epoll_wait"] RQ["ready ํ"] end CL --> TH AR --> SEL CS --> RQ TH -->|๋ค์ ๋ง๊ฐ๊น์ง timeout| SEL SEL -->|์ค๋น fdยท๋ง๋ฃ timer ์๊ฑฐ| RQ RQ -->|์คํ ํ ๋ฐ๋ณต| TH style EL fill:none,stroke:#495057,stroke-dasharray: 5 5 classDef srcYellow fill:#ffec99,stroke:#f08c00 classDef srcBlue fill:#a5d8ff,stroke:#1971c2 classDef srcGreen fill:#b2f2bb,stroke:#2f9e44 class CL,TH srcYellow class AR,SEL srcBlue class CS,RQ srcGreen
์ด ์ธ ๊ตฌ์กฐ์ ํ๋ ฅ ๊ณจ๊ฒฉ์ asyncio ์ ์ฉ์ด ์๋๋ผ reactor ํจํด์ผ๋ก, Node์ libuvยทGo ๋ฐํ์ยทnginx๋ ์ด๋ฆ๋ง ๋ฌ๋ฆฌ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ์ด๋ค.
timer๊ฐ heap์ด๋ wheel์ด๋, ๋ท๋จ์ด epoll์ด๋ kqueue๋ ์ ๋๋ง ๊ฐ๋ฆฐ๋ค.
์ฝ๋ฐฑ ํ๋์ ์ด๋ ์์
์ด์ ์ฝ๋ฐฑ ํ๋๊ฐ ์ฌ๋ฌ await๋ฅผ ๊ฑฐ์น๋ฉฐ ์ธ ๊ตฌ์กฐ ์ฌ์ด๋ฅผ ์ด๋ป๊ฒ ์ฎ๊ฒจ ๋ค๋๋์ง ๋ฐ๋ผ๊ฐ ๋ณด์.
async def handle(reader, writer):
data = await reader.read(100) # โ ์ฝ๊ธฐ I/O ๋๊ธฐ
await asyncio.sleep(0.5) # โก ์๊ฐ ๋๊ธฐ
writer.write(process(data))
await writer.drain() # โข ์ฐ๊ธฐ I/O ๋๊ธฐasyncio.create_task(handle(...))๋ก ๋์ฐ๋ฉด ๊ทธ continuation์ด ์ด๋ ๊ฒ ์ด๋ํ๋ค.
- ์์: ์ฒซ ์คํ
์ฝ๋ฐฑ์ด
call_soon์ผ๋ก ready ํ์ ์ฌ๋ผ๊ฐ ์คํ๋๊ณ ,await reader.read(100)์์ ๋ฉ์ถ๋ค. - selector:
read๊ฐ ์์ผ fd๋ฅผ selector์ ๋ฑ๋กํ๋ฉฐ continuation์ ํํนํ๋ค. epoll์ด โ๊ทธ fd ์ฝ๊ธฐ ์ค๋นโ๋ฅผ ์๋ฆฌ๋ฉด ์ฝ๋ฐฑ์ด ready ํ๋ก ์ด๋ํด ์คํ๋๊ณ , ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ๋คawait asyncio.sleep(0.5)์์ ๋ฉ์ถ๋ค. - timer heap:
sleep์ดcall_later๋ก 0.5์ด ๋ค continuation์ timer heap์ ๋ฃ๋๋ค. 0.5์ด๊ฐ ์ง๋๋ฉด ๋ง๋ฃ๋ ์ฝ๋ฐฑ์ด ready ํ๋ก ์ด๋ํด ์คํ๋๊ณ ,writer.write()๋คawait writer.drain()์์ ๋ฉ์ถ๋ค. - selector: ์ฐ๊ธฐ ๋ฒํผ๊ฐ ์ฐจ ์์ผ๋ฉด
drain์ด fd๋ฅผ ์ฐ๊ธฐ ๊ฐ์๋ก selector์ ๋ฑ๋กํ๊ณ ๋๊ธฐํ๋ค(์ฌ์ ๊ฐ ์์ผ๋ฉด ์ ๋ฉ์ถ๊ณ ํต๊ณผ). โ์ฐ๊ธฐ ๊ฐ๋ฅโ ์๋ฆผ์ ์ฝ๋ฐฑ์ด ready ํ๋ก ์ด๋ํด ์ฌ๊ฐ๋๊ณ coroutine์ด ๋๋๋ค.
์ด๋ ๊ฒฝ๋ก๋ง ๋ฝ์ผ๋ฉด ready ํ โ selector โ ready ํ โ timer heap โ ready ํ โ selector โ ready ํ๋ค.
๋งค๋ฒ โ๋๊ธฐ์์ ํํน โ ๊ณ๊ธฐ(fd ์ค๋นยท์๊ฐ ๋๋) โ ready ํ๋ก ์ด๋ โ ์คํโ์ ๋ฐ๋ณตํ๊ณ , ์คํ์ ์ธ์ ๋ ready ํ๋ฅผ ๊ฑฐ์น๋ค.
epoll๊ณผ event loop์ ๋ถ์
์ ๋ฆฌํ๋ฉด asynchronous I/O๋ ๋ ์ธต์ ์กฐํฉ์ด๋ค.
- OS์ ์ค๋น์๋ฃ ํต์ง(epoll): ์ด๋ค fd๊ฐ ์ค๋น๋๋์ง ์ปค๋์ด ์๋ ค์ค๋ค.
- cooperative yield(
await): coroutine์ด ๋๊ธฐ ์ง์ ์์ ์คํ๊ถ์ ๋๊ฒจ, ๊ทธ๋์ loop์ด ์ค๋น๋ ๋ค๋ฅธ ์ฝ๋ฐฑ์ ์ฒ๋ฆฌํ๋ค.
๊ทธ๋์ โloop์ epoll์ด ์ค fd๋ง ์ค์ผ์ค๋งํ๋ ์์ ์ธต ์๋๋โ๋ ์ ๋ฐ๋ง ๋ง๋ค.
์์ฒ fd๋ฅผ ๊ฐ์ํ๋ ๋ฌด๊ฑฐ์ด ์ผ์ ์ปค๋(epoll)์ด ๋์ ์ง๊ณ , loop์ busy polling ์์ด epoll_wait์์ ์๋ค ๊นจ๋ฉด ๋๋ค.
๋์ loop์ด ์ง์ ์ง๋ ๋ชซ๋ ๋ถ๋ช ํ๋ค
- fd์ ์ฝ๋ฐฑ์ ๋งคํ
- timer heap ์ ์ง
await๋ก ๋ฉ์ถ coroutine์ ์ค๋จยท์ฌ๊ฐ- ready ํ ์์ง
์ด๋ ค์ด ๊ฐ์๋ ์ปค๋์ ๋งก๊ธฐ๊ณ ์์ ์ โ๋๊ตฌ๋ฅผ ์ธ์ ๊นจ์ธ์งโ๋ง ๊ด๋ฆฌํ๋ ๋ถ์ ์ด๋ค.
synchronous + non-blocking polling๊ณผ์ ์ฐจ์ด
8์ ์์ ๋ณธ โnon-blocking ์์ผ์ ์ง์ ๋ฐ๋ณต ํ์ธโํ๋ ๋ฐฉ์์ ์ค๋น๋๋์ง ๊ณ์ ๋ฌผ์ด๋ณด๋๋ผ CPU๋ฅผ ํ์ด๋ค(busy polling). epoll์ โ์ค๋น๋๋ฉด ์๋ ค์ฃผ๊ฒ ๋คโ๋ ๊ฐ์ ์ญํ ์ด๋ผ ๊ทธ ๋ญ๋น๊ฐ ์๋ค. ๋ค๋ง epoll ์์ฒด๋ ํต์ง๋ง ํ ๋ฟ, ์ค์ ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋
recv()ํธ์ถ์ ์ฌ์ ํ ํ์ํ๋ค.์ฌ๊ธฐ์ ์ธต์๋ฅผ ๋๋ ์ผ ํ๋ค. ์ค๋น๋ ์์์ non-blocking
recv()๋ฅผ ๋ถ๋ฅด๋ ์ ์์ค ํธ์ถ ์์ฒด๋ ๊ทธ ์๋ฆฌ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์ผ๋ 8์ ์ synchronous + non-blocking์ด๊ณ , busy polling์ ๋๋ฌป๋ ๋ญ๋น๊ฐ ์๋ ๊ฑด sync/async ๋๋ฌธ์ด ์๋๋ผ epoll ํต์ง ๋์ด๋ค.
asyncio๋ ์ด ์ ์์ค ๋ฉ์ปค๋์ฆ(epoll ํต์ง + non-blockingrecv())์ event loop๋ก ๊ฐ์ธ, ํ๋ก๊ทธ๋๋จธ์๊ฒ๋await๋ก ๋ฑ๋กํ๊ณ ๋์ค์ ๋ฐ๋ asynchronous + non-blocking์ผ๋ก ๋ณด์ด๊ฒ ์ถ์ํํ๋ค.
12. ์ง์ง ๋ณ๋ ฌ์ ์ธ์ ๊ฐ๋ฅํ๊ฐ
์ง์ง ๋ณ๋ ฌ์ ์ฌ๋ฌ ์ฝ์ด์์ ์ฌ๋ฌ ์คํ ํ๋ฆ์ด ์ค์ ๋ก ๊ฐ์ ์๊ฐ์ ๋ฐฐ์น๋๋ ๊ฒ์ด๋ค. ํ์์กฐ๊ฑด์ ๋ ๊ฐ์ง๋ค.
- ์ฝ์ด๊ฐ ์ฌ๋ฌ ๊ฐ์ผ ๊ฒ
- ์ฌ๋ฌ OS threadยทprocess๊ฐ ์ค์ ๋ก ๊ทธ ์ฝ์ด๋ค์ ๋ฐฐ์น๋ ๊ฒ
ํต์ฌ์ ๋
ผ๋ฆฌ ์ฝ์ด์ ์ฌ๋ผ๊ฐ ์คํ๋๋ ๊ฒ์ ์ธ์ ๋ OS thread๋ผ๋ ์ ์ด๋ค.
process๋ ๊ฒฐ๊ตญ ๊ทธ ์์ thread๊ฐ ์ฝ์ด์ ์ฌ๋ผ๊ฐ๊ณ , user thread(coroutineยทgoroutine)๋ ์์ ์ ํ์์ค OS thread๊ฐ ์์ด์ผ ๋๋ค.
๊ทธ๋์ ๋ณ๋ ฌ ์ฌ๋ถ๋ โ๊ทธ ๋ชจ๋ธ์ด ์ฌ๋ฌ OS thread๋ฅผ ์ฌ๋ฌ ์ฝ์ด์ ์ค์ ๋ก ์ฌ๋ฆฌ๋๋โ๋ก ๊ฐ๋ฆฐ๋ค โ ๋จ์ผ OS thread์ธ event loop๋ง ๋ณ๋ ฌ์ด ์ ๋๊ณ , ์ฌ๋ฌ processยท์ฌ๋ฌ OS threadยทgoroutine์ ๋ณ๋ ฌ์ด ๋๋ค.
๋์์ฑ์ ๊ตฌ์กฐ๋ผ์ ์ฝ์ด๊ฐ ํ๋์ฌ๋ ์ฑ๋ฆฝํ์ง๋ง ๋ณ๋ ฌ์ฑ์ ๋ฌผ๋ฆฌ์ ์คํ์ด๋ผ ์ฌ๋ฌ ์ฝ์ด์ ์ฌ๋ฌ OS ์คํ ๋จ์๊ฐ ์ค์ ๋ก ํ์ํ๋ค.
13. GIL โ Python์ ์ ์ฝ
Python thread๊ฐ ๋ณ๋ ฌ์์ ์ ์ฝ์ ๋ฐ๋ ์ด์ ๋ GIL(Global Interpreter Lock)์ด๋ค.
CPython ์ธํฐํ๋ฆฌํฐ์๋ ํ ์๊ฐ์ ํ๋์ thread๋ง Python ๋ฐ์ดํธ์ฝ๋๋ฅผ ์คํํ๋๋ก ๋ง๋ ์ ๊ธ์ด ์๋ค.
๊ฒฐ๊ณผ๋ ๋ ๊ฐ์ง๋ค.
- thread๋ฅผ ์ฌ๋ฌ ๊ฐ ๋ง๋ค์ด๋ ์์ Python CPU ์ฐ์ฐ์ ํ ๋ฒ์ ํ๋์ฉ๋ง ๋๋ค. ๊ทธ๋์ CPU-bound ์์ ์ thread๋ก ๋๋ ๋ ๋นจ๋ผ์ง์ง ์๊ณ , ์ ํ ๋น์ฉ ํ์ ์คํ๋ ค ๋๋ ค์ง ์ ์๋ค.
- ๋ฐ๋ฉด I/O ๋๊ธฐ ์ค์๋ GIL์ด ํ๋ฆฐ๋ค. ๋คํธ์ํฌยทํ์ผ ๋๊ธฐ, ์ผ๋ถ C ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํธ์ถ ๊ตฌ๊ฐ์์๋ ๋ค๋ฅธ thread๊ฐ ์งํํ ์ ์๋ค. ๊ทธ๋์ I/O-bound ์์ ์๋ Python thread๋ ์ถฉ๋ถํ ์ธ๋ชจ ์๋ค.
ํํ ์คํด
โPython์ ๋์์ฑ์ด ์ ๋๋คโ๋ ํ๋ฆฐ ๋ง์ด๋ค. ์ ํํ๋ **โCPython์์ ์์ Python CPU ์ฐ์ฐ์ thread๋ก ๋ณ๋ ฌํํ๋ ๋ฐ ์ ์ฝ์ด ์๋คโ**๋ ๋ป์ด๋ค. I/O ๋์์ฑ์ thread๋ก๋,
asyncio๋ก๋ ์ ๋๋ค. CPU ๋ณ๋ ฌ์ด ํ์ํ๋ฉดmultiprocessing์ผ๋ก ๋ณ๋ process๋ฅผ ๋์ GIL์ ์ฐํํ๊ฑฐ๋ ๋ค์ดํฐ๋ธ ํ์ฅ์ผ๋ก ๊ฐ๋ค.
GIL์ CPython์ ์ฌ์ ์ผ ๋ฟ ๋ณดํธ ๋ฒ์น์ด ์๋๋ค.
GoยทJavaยทC++ ๊ฐ์ ์ธ์ด์๋ GIL์ด ์์ด์ thread๋ goroutine์ด ์ฌ๋ฌ ์ฝ์ด์์ ๊ณง๋ฐ๋ก ๋ณ๋ ฌ๋ก ๋๋ค. Go์ goroutine์ด CPU-bound์๋ ๊ฐํ ์ด์ ๊ฐ ์ฌ๊ธฐ์ ์๋ค.
Python๋ 3.13๋ถํฐ GIL์ ๋๋ ์คํ์ ๋น๋๋ฅผ ๋์
ํ๊ธฐ ์์ํ์ผ๋, ์์ง ๊ธฐ๋ณธ์ GIL์ด ์๋ ๋ชจ๋ธ์ด๋ค.
GIL์ด ์ ํ์ํ์ง(์ฐธ์กฐ ์นด์ดํ )์ ์ปค๋๊ณผ ๋ฌด๊ดํ ๊ทธ ๋ด๋ถ ๋์์ Python GIL์์ ๋ค๋ฃฌ๋ค.
14. ๊ฒฝ์ ์กฐ๊ฑด๊ณผ ๋๊ธฐํ
๋์์ฑ์๋ ๋๊ฐ๊ฐ ๋ฐ๋ฅธ๋ค. ์ฌ๋ฌ ์คํ ํ๋ฆ์ด ๊ฐ์ ์์(๋ณ์ยทํ์ผ)์ ๋์์ ๊ฑด๋๋ฆฌ๋ฉด, ์คํ ์์์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ ๋ฌ๋ผ์ง๋ ๋ฒ๊ทธ๊ฐ ์๊ธด๋ค.
์ด๋ฅผ race condition์ด๋ผ ํ๋ค.
๋ฐฉ์งํ๋ ๋ฐฉ๋ฒ์ ๊ณต์ ์์์ ๋์์ ์ ๊ทผํ์ง ๋ชปํ๋๋ก ์์๋ฅผ ๊ฐ์ ํ๋ ๊ฒ์ด๋ค.
lock, mutex, semaphore ๊ฐ์ ๋๊ธฐํ ๋๊ตฌ๋ก critical section์ ์ง๋ ฌํํ๋ค. ์
์ ๋ชฉ์ ์ ๊ฐ์ง๋ง ์ฑ๊ฒฉ์ด ๋ค๋ฅด๋ค.
| ๋๊ตฌ | ๋์ ํ์ฉ | ์์ ๊ถ | ํต์ฌ |
|---|---|---|---|
| lock | ๋ณดํต 1 | ๊ตฌํ๋ง๋ค | ์ ๊ธ์ ์ด์นญ์ด์ ๊ธฐ๋ณธ ์ํธ ๋ฐฐ์ |
| mutex | 1 | ์์ (์ ๊ทผ ํ๋ฆ๋ง ํด์ ) | critical section์ ํ ๋ฒ์ ํ๋์ฉ |
| semaphore | N | ์์ | ๋์ ์ ๊ทผ์ N๊ฐ๋ก ์ ํ, ์ ํธ ์ ๋ฌ |
mutex๋ โ์์ ๊ถ ์๋ 1๊ฐ์ง๋ฆฌโ(ํ์ฅ์ค ์ด์ ํ๋), semaphore๋ โ์์ ๊ถ ์๋ N๊ฐ์ง๋ฆฌโ(์ฃผ์ฐจ์ฅ ๋น์๋ฆฌ N๊ฐ)๋ก ๊ธฐ์ตํ๋ฉด ์ฝ๋ค.
๊ตฌ์ฒด์ API๋ ์ธ์ดยท๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ง๋ค ๋ค๋ฅด๋ค.
์ฉ์ด๊ฐ ๋์จํ ์ด์ โ "lock"์ ํต์นญ์ด๋ค
์ค๋ฌด์์๋ lock๊ณผ mutex๋ฅผ ๊ฑฐ์ ํผ์ฉํ๋ค. โlock์ ๊ฑด๋คโ๊ณ ํ๋ฉด ๋ณดํต mutex๋ฅผ ๋ปํ์ง๋ง, โlockโ์ด๋ผ๋ ์ด๋ฆ ์์ฒด๋ ์์ ๊ถ ์ ๋ฌด๋ฅผ ํน์ ํ์ง ์๋๋ค. ๊ทธ๋์ ๊ฐ์ โLockโ์ด๋ผ๋ ๊ตฌํ๋ง๋ค ์ฑ๊ฒฉ์ด ๋ค๋ฅด๋ค.
- Go
sync.Mutex: ์ด๋ฆ๋ Mutex๊ณ ์์ ๊ถ ์๋ ์ง์ง mutex๋ค(์ ๊ทผ goroutine๋ง ํด์ ).- Python
threading.Lock: ์ด๋ฆ์ Lock์ด์ง๋ง ์์ ๊ถ์ด ์๋ค(๋ค๋ฅธ thread๊ฐ release ๊ฐ๋ฅ). ์๋ฐํ๋ binary semaphore์ ๊ฐ๊น๊ณ , ์์ ๊ถ ์๋ ๋ฒ์ ์threading.RLock์ด๋ค.์ ํํ ๊ฐ๋ฅด๋ ค๋ฉด ์์ ๊ถ ์ ๋ฌด์ ๊ฐ์ ๋ ๊ฐ์ง๋ฅผ ๋ณธ๋ค.
์์ ๊ถ ๊ฐ์ ์ด๋ฆ ์์ 1 mutex ์์ 1 binary semaphore (ํํ ๊ทธ๋ฅ โlockโ) ์์ N counting semaphore โ์์ ๊ถ ์๋ ์ ๊ธโ์ ์ฝ ์ง๋ ์ ์ ์ฉ์ด๊ฐ binary semaphore์ด๊ณ , ์ค๋ฌด์์ ์ด๊ฒ๋ ๊ทธ๋ฅ โlockโ์ด๋ผ ๋ถ๋ฅธ๋ค.
ํ์ผ์ ๊ฑฐ๋ ์ ๊ธ๋ ๊ฐ์ ๊ฐ๋๋ค.
๋ฆฌ๋
์ค์ flock์ ์์ ๊ถ ์๋ ์ํธ๋ฐฐ์ ๋ผ mutex์ ์ฑ์ง์ ๊ฐ์ง๋ง ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋๋ผ ํ์ผ ์์คํ
๋ ๋ฒจ์ ์ ๊ธ์ด๊ณ ์์ ๋จ์๊ฐ thread๊ฐ ์๋๋ผ ํ๋ก์ธ์ค(ํ์ผ ๋์คํฌ๋ฆฝํฐ)๋ค. ๊ทธ๋์ ์ฃผ๋ก ํ๋ก์ธ์ค ๊ฐ ์ํธ๋ฐฐ์ (์: ์คํฌ๋ฆฝํธ ๋จ์ผ ์คํ ๋ณด์ฅ)์ ์ฐ๋ฉฐ, โํ๋ก์ธ์ค ๊ฐ ๋ฎคํ
์คโ๋ก ์ดํดํ๋ฉด ๋๋ค.
๋ชจ๋ธ๋ง๋ค ์ํ๋๊ฐ ๋ค๋ฅด๋ค.
- ๊ณต์ ๋ฉ๋ชจ๋ฆฌ thread: ์ํ์ด ๊ฐ์ฅ ํฌ๋ค. ์๋ฌด ๋๋ preemption๋๋ฏ๋ก ๋ thread๊ฐ ๊ฐ์ ๋ณ์๋ฅผ ๋์์ ๊ฑด๋๋ฆฌ๊ธฐ ์ฝ๋ค. lock ๊ด๋ฆฌ์ deadlock๊น์ง ์ ๊ฒฝ ์จ์ผ ํ๋ค.
- event loop: ๋จ์ผ thread๋ผ โ๋์ด ๊ฐ์ ์ค์ ๋์์ ์คํโํ๋ ๊ฒฝ์์ ์๋ค. ๋ค๋ง
await๋ก ์๋ณดํ๋ ์ฌ์ด์ ์ํ๊ฐ ๋ฐ๋ ์ ์์ด ์์ ํ ์์ ๋กญ์ง๋ ์๋ค. ์ดawait๊ฒฝ๊ณ๋ฅผ ๋ณดํธํ ๋๋ event loop๋ฅผ ๋ง๋threading.Lock์ด ์๋๋ผasyncio.Lock์ ์ด๋ค. ์ ํ ์ง์ ์ดawait๋ก ๋๋ฌ๋ ์ถ์ ์ ์ฝ๋ค. - ์ฌ๋ฌ process: ๋ฉ๋ชจ๋ฆฌ๊ฐ ๊ฒฉ๋ฆฌ๋ผ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ๊ฒฝ์์ ์๋ค. ๋์ ๊ณต์ ํ์ผยทDB ๊ฐ์ ์ธ๋ถ ์์์ ๋ํ ๊ฒฝ์์ ์ฌ์ ํ ์กด์ฌํ๋ค.
Go์ ์ ๊ทผ โ channel
Go๋ lock์ผ๋ก ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์งํค๋ ๋์ , channel์ด๋ผ๋ ํต๋ก๋ก goroutine๋ผ๋ฆฌ ๊ฐ์ ์ฃผ๊ณ ๋ฐ๊ฒ ๊ถํ๋ค. ์ ๋ช ํ ๊ฒฉ์ธ์ด ์ด๋ฅผ ์์ถํ๋ค.
๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํด์ ์ํตํ์ง ๋ง๊ณ , ์ํตํด์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ๋ผ.
(Donโt communicate by sharing memory; share memory by communicating.)
Go์๋sync.Mutex๋ ์์ผ๋, ๊ธฐ๋ณธ ๋ฐ์์ โ๊ณต์ ์ํ๋ฅผ ์ฌ๋ฟ์ด ๊ฑด๋๋ฆฌ์ง ๋ง๊ณ ๊ฐ์ ํต๋ก๋ก ๋๊ฒจ๋ผโ๋ค.
15. ๋์์ฑ ์ธต์ ํ๋์
์ง๊ธ๊น์ง์ ์คํ ๋ชจ๋ธ์ ํ๋์ ์ง๋๋ก ๋ชจ์ผ๋ฉด ๋ ์ถ์ผ๋ก ๊ฐ๋ฆฐ๋ค.
ํ๋๋ ๋จ์์ ๊ณ์ธต(process โ OS thread โ user thread)์ด๊ณ , ๋ค๋ฅธ ํ๋๋ user thread๋ฅผ OS thread์ ์น๋ ๋งคํ(N:1 / M:N)์ด๋ค.
process (๋
๋ฆฝ ๋ฉ๋ชจ๋ฆฌ) โโโโโโโ ์ฌ๋ฌ ๊ฐ = ๋ฉํฐํ๋ก์ธ์ฑ
โ OS thread (๋ฉ๋ชจ๋ฆฌ ๊ณต์ ) โโ ์ฌ๋ฌ ๊ฐ = ๋ฉํฐ์ค๋ ๋ฉ
โ user thread (kernel์ ๋ชจ๋ฆ, ๋ฐํ์ยท๋ฃจํ๊ฐ ๊ด๋ฆฌ)
โ N:1 โ event loop + coroutine
โ M:N โ goroutine / virtual thread
process โ OS thread โ user thread๋ ํฌํจ ๊ด๊ณ์ด๊ณ , N:1๊ณผ M:N์ user thread ์ธต์์๋ง ๊ฐ๋ฆฐ๋ค. event loop์ goroutine์ ๋ถ๋ชจ-์์์ด ์๋๋ผ ํ์ ๋ค.
| ๋ชจ๋ธ | ๋๋ฆฌ๋ ๋จ์ | ๋ฉ๋ชจ๋ฆฌ | kernel์ด ์๋ | ์ ํยท์ค์ผ์ค | ๋์์ฑ | ์ง์ง ๋ณ๋ ฌ | ๋ํ |
|---|---|---|---|---|---|---|---|
| ๋ฉํฐํ๋ก์ธ์ฑ | process | ์์ ๊ฒฉ๋ฆฌ | O | kernel(์ ์ ) | O | O | multiprocessing |
| ๋ฉํฐ์ค๋ ๋ฉ | OS thread | ๊ณต์ | O | kernel(์ ์ ) | O | GIL ์์ผ๋ฉด O | threading, Java thread |
| event loop | user thread (N:1) | ๊ฐ์ OS thread 1๊ฐ | X | event loop(ํ๋ ฅ, await) | O | X | asyncio, JS |
| M:N ๋ฐํ์ | user thread (M:N) | ๋ฐํ์ ๊ด๋ฆฌ | X | ๋ฐํ์(ํ๋ ฅ + ์ ์ ) | O | O | goroutine, virtual thread |
๋์์ฑ์ ๋ค ์ธต์ ๋ชจ๋ O๋ค โ ๋ท ๋ค โ์ฌ๋ฌ ์ผ์ ๊ฒน์ณ ๋ค๋ฃจ๋โ ๋์์ฑ ๋๊ตฌ๋ค.
๊ฐ๋ฆฌ๋ ๊ฑด ์ง์ง ๋ณ๋ ฌ์ด๋ฉฐ, N:1 event loop๋ง ๋จ์ผ OS thread๋ผ X๋ค.
์ธ์ด๋ณ๋ก ์ฃผ๋ก ์ด๋ ์ธต์๋ฅผ ์ฐ๋์ง ๋ณด๋ฉด ์ด๋ ๋ค.
| ์ธ์ด | process | OS thread (๋ฉํฐ์ค๋ ๋ฉ) | N:1 event loop | M:N |
|---|---|---|---|---|
| Python | O | O (I/O ๋์์ฑ O, CPU ๋ณ๋ ฌ์ GIL์ด ๋ง์) | O (asyncio) | ํ์ค์ ์์ |
| Go | ๋๋ฌพ | M:N์ ํ๋ถ | โ | O (goroutine) |
| Java | ๊ฐ๋ฅ | O (๋ณ๋ ฌ) | ๋ผ์ด๋ธ๋ฌ๋ฆฌ | O (virtual thread) |
| JS / Node | workerยทcluster | worker_threads | O (ํต์ฌ) | โ |
| Erlang / Elixir | โ | ํ๋ถ | โ | O (๊ฒฝ๋ ํ๋ก์ธ์ค) |
16. ์ด๋ค ๋๊ตฌ๋ฅผ ์ธ์ ์ฐ๋
์ง๊ธ๊น์ง์ ํ ์์ ์ค์ ๋๊ตฌ๋ฅผ ๋ฐฐ์นํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
| ๋๊ตฌ | ์คํ ๋ชจ๋ธ | ์ฃผ๋ ๊ฒ | ์ ํฉํ ์์ |
|---|---|---|---|
Python threading / ThreadPoolExecutor | OS thread(preemptive) | ๋์์ฑ (CPU ๋ณ๋ ฌ์ GIL์ด ๋ง์) | I/O-bound, ์ ์ ์์ ๋์ ์์ |
Python asyncio | ๋จ์ผ thread event loop(cooperative) | ๋์์ฑ | ๋๋ I/O-bound(์์ฒ-์๋ง ์ฐ๊ฒฐ) |
Python multiprocessing / ProcessPoolExecutor | ์ฌ๋ฌ process | ๋ณ๋ ฌ | CPU-bound |
| Go goroutine + channel | M:N runtime | ๋์์ฑ + ๋ณ๋ ฌ | I/OยทCPU ๋ ๋ค |
์ ํ ๊ธฐ์ค์ ๋๋ต ๋ค์๊ณผ ๊ฐ๋ค.
- CPU-bound์ธ๊ฐ. ์ฌ๋ฌ ์ฝ์ด์ ์ค์ ๋ก ๋๋ ์ผ ํ๋ค. Python์ด๋ฉด multiprocessingยท๋ค์ดํฐ๋ธ ํ์ฅ, Go๋ฉด goroutine.
- I/O-bound์ธ๋ฐ ๋์ ์์ ์ด ์ ์๊ฐ. thread pool๋ก ์ถฉ๋ถํ๋ค. ์ฝ๋๊ฐ ํ๋ฒํ synchronous์์ด๋ผ ์์ฑํ๊ธฐ ์ฝ๋ค.
- I/O-bound์ธ๋ฐ ๋์ ์์ ์ด ์์ฒ ๊ฐ ์ด์์ธ๊ฐ. event loop๋ goroutine. thread ์์ฒ ๊ฐ๋ ์ ํ ๋น์ฉ์ด ์ปค์ง๋ค.
- ๋์ด ์์ฌ ์๋๊ฐ. ์ค๋ฌด์์ ํํ๋ค. ๋คํธ์ํฌ ํธ์ถ์
asyncio๋ก ๊ฒน์น๊ณ , CPU ํ์ฒ๋ฆฌ๋ process pool๋ก ๋ถ๋ฆฌํ๊ณ , synchronous ์ ์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ณ๋ thread๋ก ์ฐํํ๋ค(asyncio.to_thread). Go์์๋ goroutine ํ๋๋ก ๋ ๊ฒฐ์ ๋ชจ๋ ๋ค๋ฃฌ๋ค.