Kotlin

[Kotlin] Coroutine 동시성 프로그래밍 개념 이해

실버☆ 2023. 11. 7. 16:22

 

 

 

 

💡 Coroutine

 

Co (협력) + Routine. 다양한 테스크를 병렬적으로 진행하기 위한 프로그래밍 방식이다. 코루틴은 기존의 스레드와 콜백함수를 사용했을 때 증가하는 리소스와 코드의 복잡도를 보완한다. 스레드를 사용하면 코드를 관리하기 불편하다는 단점이 있지만, 코루틴을 사용하면 훨씬 더 간편하고 코드를 보기도 편리해진다는 것!

 

코루틴은 동시에 여러 코드를 실행시킬 수 있다. 이러한 역할은 스레드와 비슷하다. 하지만 사용법에는 꽤 큰 차이가 있다. 간단한 예제로 살펴보자

 

fun main() = runBlocking {
    launch {
        delay(1000L)
        println("World!")
    }
    println("Hello")
}
//Hello
//World!

 

delay()를 통해 지정된 코루틴을 일시 중지 시켰기 때문에 "world!"보다 "Hello"가 먼저 출력된 것을 볼 수가 있다.

  • runBlocking()은 코드 내에서 새로운 코루틴 범위를 선언해준다. 이를 사용하면 runBlocking {..} 내부 코드가 실행을 완료할 때까지 runBlocking이 실행된 스레드는 blocking 즉 차단되어 다른 작업을 하지 못한다.
  • launch() 또한 독립적으로 새로운 코루틴을 생성한다. 이렇게 하면 현재 실행되고 있는 스레드에 다른 작업을 할당하여 시작할 수 있다. 하지만 기존 스레드 작업에 대한 blocking은 하지 않는다.

이들은 모두 coroutineBuilder로써, coroutineScope 내에서 코루틴을 실행시키는 역할을 한다.

 

 

 

 

💡 ScopeBuilder

 

coroutineScope 빌더를 호출하면 새로운 일시 중단 블록을 생성할 수 있다. 즉 코루틴 범위를 생성하며, 범위 내에 모든 코드가 완료될 때까지 해당 본문은 완료되지 않는다. 이는 runBlocking() 과 유사하다.

 

fun main() = runBlocking {
    doWorld()
}

suspend fun doWorld() = coroutineScope {
    launch {
        delay(1000L)
        println("World!")
    }
    println("Hello")
}

 

이 둘의 차이점은 runBlocking 은 범위 내 하위 코루틴이 완료될 때까지 현재 스레드의 작업을 차단한다는 것이다. 따라서 메인 스레드에서 해당 범위를 호출했을 때는 반응성이 떨어질 수 있다. 반면 coroutineScope 는 현재 코루틴 스코프 내에서만 차단되며, 부모 스레드 등 다른 스코프에는 영향을 미치지 않는다.

 

coroutineScope 빌더는 여러 동시 작업 코루틴을 실행하는 데 사용할 수 있다.

 

fun main() = runBlocking {
    doWorld()
    println("Done")
}

suspend fun doWorld() = coroutineScope { // this: CoroutineScope
    launch {
        delay(2000L)
        println("World 2")
    }
    launch {
        delay(1000L)
        println("World 1")
    }
    println("Hello")
}
//Hello
//World 1
//World 2
//Done

 

doWork() 내에 coroutineScope는 launch() 로 실행된 두 개의 코드 블록이 모두 완료된 후에야 완료되므로 main() 내에 있는 "Done"은 가장 마지막에 출력되었다.

 

 

 

 

💡 Job

 

코루틴 빌더는 실행된 코루틴에 대한 Job 객체를 반환하며 이를 통해 코루틴을 제어할 수 있다. join() 을 호출했을 경우 Job의 동작이 완료되기를 기다린다.

 

val job = launch {
    delay(1000L)
    println("World!")
}
println("Hello")
job.join()
println("Done")

 

job의 코루틴이 완료될 때까지 일시중지했다가 job이 완료되면 다시 작업이 재개되면서 "Done"이 출력된다.

 

또한 코루틴의 Job은 작업의 수명 주기에 따라 다양한 상태를 가지고 있기 때문에 코루틴 실행중 원하는 시점에 작업을 해야 하는 경우 유용하게 사용할 수 있다.

 

 

 

 

 

 

참고: Kotlin 공식 문서

'Kotlin' 카테고리의 다른 글

[Kotlin] Object 키워드 / 싱글톤 패턴 (Singleton pattern)  (0) 2022.03.28