Thread vs Coroutine
Last updated
Last updated
๐ค๐ป ๊ฐ๋ณ๊ฒ ๋ค์ ์ง์ด๋ณด๊ธฐ
๋๊ธฐ : ์ด๋ค ์์ฒญ์ ๋ณด๋ธ ๋ค, ๊ทธ ์์ฒญ์ ๊ฒฐ๊ณผ๊ฐ์ ์ป๊ธฐ๊น์ง ์์ ์ ๋ฉ์ถ๋ ๊ฒ ๋น๋๊ธฐ : ์ด๋ค ์์ฒญ์ ๋ณด๋ธ ๋ค, ๊ทธ ์์ฒญ์ ๊ฒฐ๊ณผ๊ฐ์ด ์ค๊ธฐ๊น์ง ๋ฉ์ถ์ง ์๊ณ ๋ ๋ค๋ฅธ ์ผ์ ์ํํ๋ ๊ฒ
์ฐ๋ ๋์ ์ฝ๋ฃจํด์ ์ฐจ์ด์ ์ ๊ดํด ์์๋ณด๊ธฐ ์ ์, ๋ช ๊ฐ์ง ์ ์์ง์์ ์ดํด๋ณด์!
Process : ๋ณด์กฐ๊ธฐ์ต์ฅ์น์ 'ํ๋ก๊ทธ๋จ'์ด **๋ฉ๋ชจ๋ฆฌ ์์ผ๋ก ์ ์ฌ๋์ด ์คํ๋๋ฉด 'ํ๋ก์ธ์ค'**๊ฐ ๋๋ค. Thread : ๊ฐ์ Process ๋ด์์ ์คํ๋๋ ์ฌ๋ฌ ์์ (ํ๋ฆ)์ ๋จ์
Process ๋ ๋ ๋ฆฝ๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ธ 'ํ'์ ํ ๋น๋ฐ๋๋ค.
Thread ๋ Process ํ์์ ์ข ์๋๋ ๋ณด๋ค ์์ ๋จ์์ด๊ณ , ๊ฐ ์ฐ๋ ๋๋ ๋ ๋ฆฝ๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ธ ์คํ(Stack) ์ ๊ฐ๋๋ค. Thread ๋ฅผ ํ๋ ์์ฑํ๋ฉด, ํ๋์ ์คํ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๊ธฐ๋ ๊ฒ์ด๋ค. ๊ฐ ์ฐ๋ ๋๋ ๋ค๋ฅธ ์ฐ๋ ๋์๊ฒ ์คํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ ํ ์ ์๋ค. ํ์ง๋ง ํ๋ก์ธ์ค์ ํ์ ์ํ ๋ชจ๋ Thread ๊ฐ ๊ณต์ ํ ์ ์๋ค.
๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ๋ง ๊ทธ๋๋ก ๋์์ ์ฌ๋ฌ ์์ ์ ์ํํ๋ ๊ฒ์ด๋ค. ํ์ง๋ง ๋์ผ๋ก ๋ณด๊ธฐ์ ๋์์ ์คํ๋๋ ๊ฒ์ด์ง, ์ฌ์ค ์๋ถํ (Interleaving) ๊ธฐ๋ฒ์ ํ์ฉํ์ฌ ์ฌ๋ฌ ์์ ์ ์กฐ๊ธ์ฉ ๋๋์ด์ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์คํํ๋ ๊ฒ์ด๋ค.
์ ์์ ๋ฅผ ์ดํด๋ณด๋ฉด, Task 1 ๊ณผ Task 2 ๋ฅผ ์๊ฐ ์ชผ๊ฐ์ด ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์ํํ์ฌ ์ฌ์ฉ์ ์ ์ฅ์์ ๋ ์์ ์ด ๋์์ ์ผ์ด๋๋ ๊ฒ์ฒ๋ผ ๋๊ปด์ง๊ฒ ๋๋ค. ๋ฐ๋ผ์ 10๋ถ + 10๋ถ, ์ด 20๋ถ์ด ์์๋๋ค. (Context Switching ๊ณ ๋ ค X)
๋ณ๋ ฌ์ฑ ํ๋ก๊ทธ๋๋ฐ์ ์๋ถํ ๊ธฐ๋ฒ์์ด ์ฐ์ผ๋ก ์ฌ๋ฌ ์์ ์ ํ ๋ฒ์ ๋์์ ์ํํ๋ ๊ฒ์ธ๋ฐ, ์์(CPU ์ฝ์ด)์ ์ ์ฅ์์ ์๊ธฐ๋ ์๊ธฐ ํ ์ผ 1๊ฐ๋ฅผ ํ๋ ๊ฒ ๋ฟ์ด๋ค. ์ฆ, ๋ณ๋ ฌ์ฑ์ '์์(CPU ์ฝ์ด)์ด ์ฌ๋ฌ ๊ฐ' ์ผ ๋ ๊ฐ๋ฅํ๋ค.
์ ์์๋ฅผ ๋ณด์. Task 1 ๊ณผ Task 2 ๊ฐ ๋ณ๋ ฌ์ ์ผ๋ก ๋์์ ์ํ๋๋ค. ์ด๋ '๋ฉํฐ์ฝ์ด' ์์คํ ์์ ๊ฐ๋ฅํ ์ด์ผ๊ธฐ์ด๋ค. ์ฝ์ด ๊ฐ๊ฐ์ด Task 1, Task 2 ๋ฅผ ๋งก์ ์์ ์ ์ํํ๋ฉด, ์์ ํ ๋์์ ์ํ๋๋ ๊ฒ์ด๋ค. ๋ฐ๋ผ์, ๊ฐ๊ฐ ํ์คํฌ๊ฐ 10๋ถ์ฉ์ด๋ผ๋ฉด, ์ต์ข ์ ์ผ๋ก 10๋ถ์ด ์์๋๋ ๊ฒ์ด๋ค. ์ด ๊ฒฝ์ฐ Context Switching ์ด ์ผ์ด๋์ง ์๋๋ค.
Thread ์ Coroutine ์ ๋ชจ๋ '๋์์ฑ ํ๋ก๊ทธ๋๋ฐ'์ ์ํ ๊ธฐ์ ์ด๋ค. ์ด์ ๋ถํฐ, '๋์์ฑ'์ ๋ณด์ฅํ๊ธฐ ์ํด ๋ฑ์ฅํ ๋ ๊ธฐ์ ์ธ Thread ์ Coroutine ์ ๊ฐ๋ ๊ณผ ์ฐจ์ด์ ์ ๋ํ์ฌ ์์ธํ ์์๋ณด์.
์ฐ๋ ๋๋ ๊ฐ ํ์คํฌ์ ํด๋นํ๋ ์คํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋น๋ฐ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ ์์ ์ ๋์์ ์ํํด์ผํ ๋ OS ๋ ์ด๋ค ์ฐ๋ ๋ ์์ ์ ๋จผ์ ์ํํ ์ง, ์ด๋ค ์ฐ๋ ๋๋ฅผ ๋ ๋ง์ด ์ํํด์ผ ํจ์จ์ ์ธ์ง์ ๋ํ ์ค์ผ์ฅด๋ง (์ ์ ์ค์ผ์ฅด๋ง, Preempting Scheduling) ์ ํด์ผ ํ๋ค.
Coroutuine ์ Lightweight Thread ๋ผ๊ณ ๋ถ๋ฅธ๋ค. (์ฝํ๋ฆฐ ๊ธฐ์ค, ๊ณต์ ๋ฌธ์์๋ ์ด๋ ๊ฒ ์ค๋ช ๋์ด ์๋ค) ๋ง์ฐฌ๊ฐ์ง๋ก ์์ ํ๋ํ๋๋ฅผ ํจ์จ์ ์ผ๋ก ๋ถ๋ฐฐํด์ ๋์์ฑ์ ๋ณด์ฅํ๋ ๊ฒ์ ๋ชฉํ๋ก ํ์ง๋ง, ์์ ํ๋ํ๋์ Thread ๋ฅผ ํ ๋นํ๋ ๊ฒ์ด ์๋ 'Object' ๋ฅผ ํ ๋นํด์ฃผ๊ณ , ์ด Object ๋ฅผ ์์ ๋กญ๊ฒ ์ค์์นญํจ์ผ๋ก์จ Context Switching ๋น์ฉ์ ๋ํญ ์ค์ธ ๊ฒ์ด๋ค.
์์ ํ๋ํ๋์ ๋จ์ : Thread
๊ฐ Thread ๊ฐ ๋ ๋ฆฝ์ ์ธ Stack ๋ฉ๋ชจ๋ฆฌ ์์ญ ๊ฐ์ง
๋์์ฑ ๋ณด์ฅ ์๋จ : Context Switching
์ด์์ฒด์ ์ปค๋์ ์ํ Context Switching ์ ํตํด ๋์์ฑ ๋ณด์ฅ
๋ธ๋กํน (Blocking) : Thread A ๊ฐ Thread B ์ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ธฐ๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ค๋ฉด, Thread A ์ ๋ธ๋กํน๋์ด Thread B ์ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ๋ ๊น์ง ํด๋น ์์์ ๋ชป ์
์๋ ์์ ์ฌ์ง์ ์ดํด๋ณด์.
Thread A ์์ Task 1 ์ ์ํํ๋ค๊ฐ Task 2 ์ ๊ฒฐ๊ณผ๊ฐ ํ์ํ ๋, ๋น๋๊ธฐ์ ์ผ๋ก Thread B ๋ฅผ ํธ์ถ์ ํ๊ฒ ๋๋ค. ์ด ๋ Thread A ๋ ๋ธ๋กํน๋๊ณ , Thread B ๋ก Context Switching ์ด ์ผ์ด๋ Task 2 ๋ฅผ ์ํํ๋ค. Task 2 ๊ฐ ์๋ฃ๋๋ฉด, ๋ค์ Thread A ๋ก Context Switching ์ด ์ผ์ด๋ ๊ฒฐ๊ณผ๊ฐ์ Task 1 ์ ๋ฐํํ๋ค.
๋์์ ๊ฐ์ด ์ํํ Task 3, Task 4 ๋ ๊ฐ๊ฐ Thread C ์ D ์ ํ ๋น๋๊ณ , ์ด์ฒด์ ์ผ๋ก ๋ดค์ ๋ ์ปค๋ ์ ์ฅ์์ Preempting Scheduling ์ ํตํ์ฌ ๊ฐ ํ์คํฌ๋ฅผ ์ผ๋งํผ ์ํํ ์ง, ํน์ ๋ฌด์์ ๋จผ์ ์ํํ ์ง๋ฅผ ๊ฒฐ์ ํ์ฌ ์๋ง๊ฒ ๋์์ฑ์ ๋ณด์ฅํ๊ฒ ๋๋ ๊ฒ์ด๋ค.
์์ ํ๋ํ๋์ ๋จ์ : Coroutine Object
์ฌ๋ฌ ์์ ๊ฐ๊ฐ์ Object ๋ฅผ ํ ๋นํจ
Coroutine Object ๋ ์์ฐํ ๊ฐ์ฒด์ด๊ธฐ ๋๋ฌธ์ JVM Heap ์ ์ ์ฌ ๋จ (์ฝํ๋ฆฐ ๊ธฐ์ค)
๋์์ฑ ๋ณด์ฅ ์๋จ : Programmer Switching (No-Context Switching)
ํ๋ก๊ทธ๋๋จธ์ ์ฝ๋๋ฅผ ํตํด Switching ์์ ์ ๋ง์๋๋ก ์ ํจ (OS ๊ด์ฌ X)
Suspend (Non-Blocking) : Object 1 ์ด Object 2 ์ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ธฐ๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ค๋ฉด, Object 1 ์ Suspend ๋์ง๋ง, Object 1 ์ ์ํํ๋ Thread ๋ ๊ทธ๋๋ก ์ ํจํ๊ธฐ ๋๋ฌธ์ Object 2 ๋ Object 1 ๊ณผ ๋์ผํ Thread ์์ ์คํ๋ ์ ์์
์ดํด๋ฅผ ์ํด ์๋ ์์ ์ฌ์ง์ ์ดํด๋ณด์.
์์ ๋จ์๋ Coroutine Object ์ด๋ฏ๋ก, Task 1 ์ ์ํํ๋ค๊ฐ ๋น๋๊ธฐ ์์ Task 2 ๊ฐ ๋ฐ์ํ๋๋ผ๋, Context Switching ์์ด ๊ฐ์ Thread ์์ Task 2 ๋ฅผ ์ํํ ์ ์๊ณ , ๋งจ ์ค๋ฅธ์ชฝ ๊ฒฝ์ฐ์ฒ๋ผ ํ๋์ Thread ์์ ์ฌ๋ฌ Coroutine Object ๋ค์ ๊ฐ์ด ์ํํ ์๋ ์๋ค. ํ ์ฐ๋ ๋์์ ๋ค์์ Coroutine ์ ์ํํ ์ ์๊ณ , Context Switching ์ด ํ์์๋ ํน์ฑ์ ๋ฐ๋ผ Coroutine ์ Light-weight Thread ๋ผ๊ณ ๋ถ๋ฅด๋ ๊ฒ์ด๋ค.
๊ทธ๋ฐ๋ฐ ์ ๊ฒฝ์ฐ๋ฅผ ๋ค์ ๋ณด์. Thread A ์ C ๊ฐ ๋์์ ์ํ๋๋ ๋ชจ์ต์ด๋ค. ์ด๋ฌ๋ฉด ๊ฒฐ๊ตญ ๋์์ฑ ๋ณด์ฅ์ ์ํด์ Context Switching ์ด ํ์ํ ๊ฒฝ์ฐ๋ค. ๋ฐ๋ผ์, Coroutine ์ 'No-Context Switching' ์ฅ์ ์ ๊ทน๊ฐ์ผ๋ก ๋์ด์ฌ๋ฆฌ๊ธฐ ์ํด, ๋จ์ผ Thread ์์ ์ฌ๋ฌ Coroutine Object ๋ฅผ ์ปจํธ๋กคํ๋ ๊ฒ์ด ์ข๋ค. (๋๋ ๊ถ์ฅํ๋ค)
๐ก ์ฌ๊ธฐ์ ์ ์ ์๋ ์
Coroutine ์ Thread ์ ๋์์ด ์๋๋ผ, Thread ๋ฅผ ๋ ์๊ฒ ์ชผ๊ฐ์ด ์ฌ์ฉํ๊ธฐ ์ํ ๊ฐ๋ ์ด๋ค.
์์ ์ ๋จ์๋ฅผ Object ๋ก ์ถ์ํ๋ฉด์ ํ๋์ Thread ๊ฐ ๋ค์์ ์ฝ๋ฃจํด์ ๋ค๋ฃฐ ์ ์๊ธฐ ๋๋ฌธ์, ์์ ํ๋ํ๋์ Thread ๋ฅผ ํ ๋นํ๋ฉฐ ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น, Context Switching ๋น์ฉ ๋ญ๋น๋ฅผ ํ ํ์๊ฐ ์์
๊ฐ์ ํ๋ก์ธ์ค ๋ด์ Heap ์ ๋ํ Locking ๊ฑฑ์ ๋ํ ์ฌ๋ผ์ง
ํ ๋ง๋๋ก, ์ฝ๋ฃจํด์ ํ๋ก๊ทธ๋๋จธ์ ๋ชฉ์ ๊ณผ ์๋๋๋ก ํจ์จ์ฑ์ ์ฌ๋ฆด ์ ์๋ ๋์์ฑ ๋ณด์ฅ ๊ธฐ๋ฒ์ด๋ค.
๊ณผ๊ฑฐ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ผ ํจ์ DB ํธ๋์ญ์ , ๋คํธ์ํน ์์ฒญ ๋ฑ์ ์ด์ผ๊ธฐํ๋๋ฐ, ์ต๊ทผ์๋ ์ด๋ฌํ ์์ ์ด ์๋๋๋ผ๋ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ ๋ชฉํ๋ ๊ฒ์ ์ฝ๊ฒ ์ฐพ์๋ณผ ์ ์๋ค. ๊ทธ๋งํผ ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๊ฐํธํด์ก๋ค๋ ์ด์ผ๊ธฐ์ธ ๊ฒ ๊ฐ๋ค. ๊ทธ๋ฆฌ๊ณ ์ด ๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ๊ฐํธํด์ง์ '์ฝ๋ฃจํด'์ด ๋ง์ ๊ธฐ์ฌ๋ฅผ ํ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค. ์๋ํ๋ฉด, ํ๋ก์ธ์ค์ ์์ ์์ ๋จ์์ธ Thread ๋ฅผ ๋ ์๊ฒ ์ชผ๊ฐ์ด ๊ด๋ฆฌํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
ํต์ฌ์ ์ฝ๋ฃจํด์ด ์ฐ๋ ๋์ ๋์์ผ๋ก ๋ฑ์ฅํ ๊ฒ์ด ์๋๊ณ , ์์ ๊ฐ์ ์ฐจ์ด์ ์ด ์๋ ๋๋ค๋ฅธ ๋์์ฑ ๋ณด์ฅ ๋ฐฉ๋ฒ์ผ๋ก ์์๋๋ฉด ๋๋ค๋ ์ ์ด๋ค. Thread ๊ธฐ๋ฒ์ ๋นํด ๋ค๋ฐฉ๋ฉด์์ ๋น์ฉ์ด ์ ๊ฐ๋๊ธฐ ๋๋ฌธ์, ์ ๊ทน์ ์ผ๋ก ํ์ฉํด๋ณด์.
์ถ์ฒ: https://velog.io/@haero_kim/Thread-vs-Coroutine-%EB%B9%84%EA%B5%90%ED%95%B4%EB%B3%B4%EA%B8%B0