#1 Unstructured Concurrency
์ฝ๋ฃจํด ์ฝ๋๋ฅผ ์ค๊ณํ ๋ ์กฐ์ฌํด์ผ ํ๋ ์ ์ด ์๋ค. ๋ค์ ์ฝ๋๋ฅผ ๋ณด์.
#1-1 ์ฝ๋
import kotlinx.coroutines.*
class MyClass {
suspend fun getMyCount(): Int {
var count = 0
CoroutineScope(Dispatchers.IO).launch {
delay(3000)
count += 50
}
return count
}
}
suspend fun main() {
println(MyClass().getMyCount())
}
/* ์ถ๋ ฅ ๊ฒฐ๊ณผ
0
*/
getMyCount()๋ผ๋ Suspending Function์ count += 50์ ์ํํ๋ ํ์ Suspending Function์ ๊ฐ์ง๊ณ ์๋ค. ํ๋ก๊ทธ๋๋จธ๋ getMyCount()๋ฅผ ํธ์ถํ๋ฉฐ, ๊ทธ ํ์ Suspending Function๊น์ง ์ ๋๋ก ๋์ํ๊ธธ ๋ฐ๋ฌ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ก 50์ด ์ถ๋ ฅ๋๋ ๊ฒ์ ๊ธฐ๋ํ๋ค. ํ์ง๋ง, ์ค์ ๋ก ์ถ๋ ฅ๋ ๊ฒ์ 0์ด๋ค. ์ด๋ count์ += 50 ํ๋ ๊ฑธ ๊ธฐ๋ค๋ฆฌ์ง(Suspend)ํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ ์ผ์ด๋ค.
Unstructured Concurrency๋ ํ์ Suspending Function๋ค์ด ์ ๋ถ return(์๋ฃ)๋๊ธฐ ์ ์, ์์ Suspending Function์ด return(์๋ฃ)๋ ์๋ ์๋ ๊ตฌ์กฐ๋ฅผ ๋งํ๋ค. Unstructured Concurrency๋ ์์ ๊ฐ์ด ํ๋ก๊ทธ๋๋จธ์ ์๋๋๋ก ์๋ํ์ง ์๋๋ค๋ ๋ฌธ์ ๋ ์์ง๋ง, ์์ Suspending Function๊ฐ ์ข ๋ฃ๋์์์๋ ํ์ Suspending Function๊ฐ ์ข ๋ฃ๋์ง ์๊ณ ๋์๊ฐ๋ค๋ ๋ฌธ์ ๋ ์๋ค. ์ด๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ญ๋น์ํค๋ฉฐ, ์์๋ถ๊ฐ๋ฅํ ์๋ฌ๊น์ง๋ ๋ฐ์์ํฌ ์ ์ฌ์ฑ์ ์ง๋๋ค.
Structured Concurrency๋ ๋ฐ๋๋ก, ์์ Suspending Function return(์๋ฃ) ์ ์, ๊ทธ ์์ ๋ชจ๋ ํ์ Suspending Function๋ค์ด ์ ๋ถ return(์๋ฃ)๋จ์ ๋ณด์ฅํ๋ ๊ตฌ์กฐ๋ค.
#1-2 ์ฝ๋ ๋ณด์
import kotlinx.coroutines.*
class MyClass {
suspend fun getMyCount(): Int {
var count = 0
val myJob = CoroutineScope(Dispatchers.IO).launch {
delay(3000)
count += 50
}
myJob.join()
return count
}
}
suspend fun main() {
println(MyClass().getMyCount())
}
/* ์ถ๋ ฅ ๊ฒฐ๊ณผ
50
*/
#1-1์ ์ฝ๋๋ฅผ ๋ณด์ํ๋ค. ๊ทธ์ , ๊ธฐ๋ค๋ฆฌ๋ฉด ๋๋ค. Job.join(), Deferred.await(), ReceiveChannel.receive() ํจ์๋ฅผ ์ฌ์ฉํ๋ค.
ํ์ง๋ง, ์ด ์ฝ๋๋ ์ฌ์ ํ Structured Concurrency๊ฐ ์๋๋ผ, Unstructured Concurrency๋ค. ์๋ํ๋ฉด, ๊ตฌ์กฐ๊ฐ ๋ณํ ๊ฒ์ ์๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ค ํด๋์ค์ public ํ๋กํผํฐ๋ฅผ ์๋ฐํ๊ฒ ์ฌ์ฉํ๋ค๊ณ private ํ๋กํผํฐ๋ก ์ทจ๊ธ๋ ์ ์๋ ๊ฒ์ฒ๋ผ, Job.join(), Deferred.await(), ReceiveChannel.receive() ๋ฑ์ ํจ์๋ก ๊ตฌ์กฐ๋ฅผ ๋ณด์ํ๋ค๊ณ Unstructured Concurrency๋ฅผ Structured Concurrency๋ก ์ทจ๊ธํ ์๋ ์๋ ๋ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด, Structured Concurrency๋ ๋์ฒด ์ด๋ค ๊ตฌ์กฐ์ธ๊ฐ?
#2 Structured Concurrency (coroutineScope)
#2-1 CoroutineScope (๋๋ฌธ์ C)
CoroutineScope
CoroutineScope Defines a scope for new coroutines. Every coroutine builder (like launch, async, etc.) is an extension on CoroutineScope and inherits its coroutineContext to automatically propagate all its elements and cancellation. The best ways to obtain
kotlinlang.org
์ฐ๋ฆฌ๊ฐ ์ ์๋ ๊ทธ CoroutineScope.
#2-2 coroutineScope (์๋ฌธ์ c)
coroutineScope
Creates a CoroutineScope and calls the specified suspend block with this scope. The provided scope inherits its coroutineContext from the outer scope, using the Job from that context as the parent for a new Job. This function is designed for concurrent dec
kotlinlang.org
Structured Concurrency๋ ๋ฐ๋ก coroutineScope๋ฅผ ์ฌ์ฉํ ์ฝ๋๋ฅผ ์๋ฏธํ๋ค. coroutineScope์ c๋ ์๋ฌธ์๋ค. ์ฐ๋ฆฌ๊ฐ ์๋ ๊ทธ CoroutineScope๊ฐ ์๋๋ค. coroutineScope๋ runBlocking์ฒ๋ผ ๊ทธ ์์ ๋ชจ๋ Suspending Function์ ๊ธฐ๋ค๋ฆฐ ํ์ ์ข ๋ฃ(์๋ฃ)๋๋ค. ๋ฌผ๋ก coroutineScope์ ๋น๋๊ธฐ ํจ์๊ณ , runBlocking์ ๋๊ธฐ ํจ์๋ผ๋ ์ฐจ์ด๊ฐ ์๋ค. CoroutineScope์ ์ด๋ฆ์ด ๋น์ทํด์ ๋ญ๊ฐ ์ถ์ง๋ง, ๊ทธ์ Job.join(), Deferred.await(), ReceiveChannel.receive()๊ฐ ์์์ ์ผ๋ก ์ํ๋๋ ํจ์๋ผ๊ณ ์๊ฐํ๋ฉด ๋๋ค. ์ฆ, ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ช ์์ ์ผ๋ก ์ ๊ฒฝ์ฐ์ง ์์๋, ํ์ Suspending Function์ ์๋ฃ๋ฅผ ๋ณด์ฅํ๋ค๋ ๋ง์ด๋ค. ํ๋ก๊ทธ๋๋จธ๋ ๋ฌด์จ ์ง์ ํด๋ ํ์ Suspending Function์ ์๋ฃ ์ ์ coroutineScope๋ฅผ ์ข ๋ฃ์ํฌ ์ ์๋ค. ์ฆ, ์ผ์ข ์ ๋ฌด๊ฒฐ์ฑ์ด ๋ณด์ฅ๋๋ ๊ตฌ์กฐ๊ฐ ๋ง๋ค์ด์ง๋ ๊ฒ์ด๋ค.
#2-3 ์ฝ๋
import kotlinx.coroutines.*
class MyClass {
suspend fun getMyCount(): Int {
var count = 0
coroutineScope {
launch {
delay(5000)
count += 50
}
launch {
delay(3000)
count += 30
}
}
return count
}
}
suspend fun main() {
println(MyClass().getMyCount())
}
/* ์ถ๋ ฅ ๊ฒฐ๊ณผ
80
*/
์์์ ์ผ๋ก ์ํ๋ Suspending Function๋ค ๋์, ํ๋ก๊ทธ๋๋จธ๋ ์๋ํ ๊ฐ์ ์ป์๋ค. ๋ค์ผ๋ก, ์ฝ๋๋๋ ์ค์๋ค.
#2-4 ์ฃผ์ํ ์ (coroutineScope์ ๋ฒ์)
...
coroutineScope {
launch(Dispatchers.IO) {
...
}
}
...
ํจ์ coroutineScope { ... }๋ ๋ฒ์ ์ง์ ํจ์์ ๋น์ทํ๋ค. ๊ทธ๋์ ์์ฑ์ ์ธ์๊ฐ ์๋ค. coroutineScope์ CoroutineContext๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ถ์ผ๋ฉด, Coroutine builder์ ์์ ๊ฐ์ด CoroutineContext๋ฅผ ๋งค๊ฐ๋ณ์๋ก ์ฃผ๋ฉด ๋๋ค.
coroutineScope์ Structured Concurrency๋ฅผ ๋ณด์ฅํ๋ค๊ณ ํ๋ค. ๊ฒ๋ค๊ฐ ๋ฒ์ ์ง์ ํจ์๋ ์๋์ด๋ ๋น์ทํ ๊ธฐ์ ๊ฐ ์๋ค๊ณ ๋ ํ๋ค. ์ด ๋ง์, coroutineScope๊ฐ ๋ณด์ฅํ๋ Structured Concurrency๋ ์ค์ง coroutineScope์ ๋ฒ์๋ง์ผ๋ก ํ์ ๋๋ค๋ ์๊ธฐ๋ค. ๋ค์ ์ฝ๋๋ฅผ ๋ณด์.
import kotlinx.coroutines.*
class MyClass {
suspend fun getMyCount(): Int {
var count = 0
coroutineScope {
CoroutineScope(Dispatchers.Default).launch {
delay(5000)
count += 50
}
CoroutineScope(Dispatchers.Default).launch {
delay(3000)
count += 30
}
}
return count
}
}
suspend fun main() {
println(MyClass().getMyCount())
}
/* ์ถ๋ ฅ ๊ฒฐ๊ณผ
0
*/
์ถ๋ ฅ ๊ฒฐ๊ณผ๊ฐ 80์ด ์๋ 0์ด๋ค. ์๋กญ๊ฒ CoroutineScope๋ฅผ ๋ง๋ค์๊ธฐ ๋๋ฌธ์ด๋ค. ์ ์์ญ(Scope)์ coroutineScope์ Structured Concurrency๊ฐ ๋ณด์ฅ๋์ง ์๋๋ค. coroutineScope ์์์ ๋ ๋ค๋ฅธ CoroutineScope๋ฅผ ์ฌ์ฉํ์ง ์๊ฒ ์ฃผ์ํ์. coroutineScope ๋ํ CoroutineScope์ ๋ง์ฐฌ๊ฐ์ง๋ก, ๋ถ๋ชจ-์์ ๊ณ์ธต์ ์ด๋ค์ผ ์์ ์ฝ๋ฃจํด์ ์์์ join()์ด ์ํ๋๋ค.
#3 ์์ฝ
๋ง์น private ์ ๊ทผ์ง์ ์์ฒ๋ผ, 'c'oroutineScope๋ ์ผ์ข ์ ๋ฌด๊ฒฐ์ฑ์ด ์ ์ง๋๋ ์์ญ์ ๋ง๋ ๋ค.
'๊นจ์ ๊ฐ๋ ๐ > Kotlin' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [Kotlin] Coroutines - ์ค๋ ๋ ์ ํ (0) | 2024.02.19 |
|---|---|
| [Kotlin] Coroutines - Parallel Decomposition (0) | 2024.02.17 |
| [Kotlin] Couroutine - ์ค๋ ๋(Thread)์ ์ค๋ ๋ ํ(Thread Pool) (2) | 2024.02.15 |
| [Kotlin] Coroutines - suspend ํค์๋ (0) | 2024.02.14 |
| [Kotlin] Coroutines - runBlocking (1) | 2024.02.13 |