마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

coroutineScope와 CorutineScope차

0 추천

아래 코드는 결과가 120 

var count = 0
lateinit var deferred : Deferred<Int>

suspend fun getTotalUserCount() : Int {
    coroutineScope {
        launch(Dispatchers.IO) {
            delay(1000)
            count = 50
        }

        deferred = async(Dispatchers.IO) {
            delay(3000)
            return@async 70
        }
    }
    return count + deferred.await()
}

아래 이코드는 결과가 70

suspend fun getTotalUserCount() : Int {
    var count = 0

    CoroutineScope(Dispatchers.IO).launch {
        delay(1000)
        count = 50
    }

    val deferred = CoroutineScope(Dispatchers.IO).async {
        delay(3000)
        return@async 70
    }
    return count + deferred.await()
}

왜 두개의 코드가 서로 다른결과인가요?

await을 하면 기다리는거로 알고있는데, 왜 50+70이 아닌 0+70 이 되는건가요?

 

수원통학러 (3,570 포인트) 님이 2021년 10월 31일 질문

1개의 답변

0 추천

첫번째와 두번째의 제일 큰 차이 점은 Scope의 차이입니다.

suspend fun getTotalUserCount() : Int {
    coroutineScope {
        launch(Dispatchers.IO) {
            delay(1000)
            count = 50
        }

        deferred = async(Dispatchers.IO) {
            delay(3000)
            return@async 70
        }
    }
    return count + deferred.await()
}

>>>>> getTotalUserCount begins
>>>>> getTotalUserCount.lauch begins
>>>>> getTotalUserCount.async begins
>>>>> getTotalUserCount.lauch ends count = 50
>>>>> getTotalUserCount.async ends
>>>>> getTotalUserCount return called
>>>>> getTotalUserCount: 120

첫번째는 확장함수를 통해 Coroutine Scope을 한 개 생성하고 동일한 Scope 안에서 모든 동작이 수행됩니다. 따라서 coroutineScope 내부의 모든 job들이 완료될 때까지 대기하게 됩니다.  coroutineScoped 블록이 완전히 처리되고  50 + 70 이  리턴됩니다.

하지만 두번째는

    CoroutineScope(Dispatchers.IO).launch {

    }

    val deferred = CoroutineScope(Dispatchers.IO).async {

    }

   return count + deferred.await()


>>>>> getTotalUserCount begins
>>>>> getTotalUserCount.launch begins
>>>>> getTotalUserCount return called. count = 0
>>>>> getTotalUserCount.async begins
>>>>> getTotalUserCount.launch ends
>>>>> getTotalUserCount.async ends
>>>>> getTotalUserCount: 70

 

이렇게 CorountineScope 생성자를 통해 각기 다른 CoroutineScope을 두개 생성했기 때문에 lauch와 async는 다른 하나가 끝날 때까지 기다려 주지 않습니다.  그렇기 때문에  launch 블록은 혼자 독립적으로 실행이 되고 끝나고 deferred.await이 결과를 받을 때까지 대기하게 됩니다. 따라서 count 의 값은 return이 호출될 때의 값인 0이 되고 deferred 의 결과는 70이 됩니다.

CoroutineScope(Dispatchers.IO).launch {
 }

val deferred = CoroutineScope(Dispatchers.IO).async {

}.await()

return count + deferred

위처럼 await를 return 전에 호출하면 동일한 결과 값이 나옴을 알 수 있습니다. 하지만 어떻게 Scope을 생성하고 배치하느냐에 따라 다른 결과가 나오기가 쉽습니다.  따라서 최대한 직관적으로 이해가 갈 수 있도록 코드를 짜야할 필요가 있습니다.

spark (227,830 포인트) 님이 2021년 10월 31일 답변
spark님이 2021년 10월 31일 수정
...