Coroutine Context와 Dispatcher 3편 - Thread 전환 하기, Context 내부의 Job, Coroutine의 자식들

2023. 2. 22. 23:05·공식 문서 번역/Coroutines 공식 문서
반응형

Thread 전환 하기

다음 코드를 JVM option에 -Dkotlinx.coroutines.debug를 넣어 실행시켜보자(debug 확인). 

 

newSingleThreadContext("Ctx1").use { ctx1 ->
    newSingleThreadContext("Ctx2").use { ctx2 ->
        runBlocking(ctx1) {
            log("Started in ctx1")
            withContext(ctx2) {
                log("Working in ctx2")
            }
            log("Back to ctx1")
        }
    }
}

📌 전체 코드는 이곳에서 확인할 수 있습니다.

 

이는 몇가지 새로운 기술들을 보여준다. 하나는 runBlocking을 명시적으로 구체화된 Context와 함께 사용하는 것이고, 다른 하나는 아래 출력 에서 볼 수 있듯이 withContext 함수를 같은 Coroutine에 계속 있으면서 Context를 바꾸는데 사용하는 것이다.

 

[Ctx1 @coroutine#1] Started in ctx1
[Ctx2 @coroutine#1] Working in ctx2
[Ctx1 @coroutine#1] Back to ctx1

 

또한 이 예제에서는 Kotlin 표준 라이브러리의 use 함수를 newSingleThreadContext에 의해 생성된 스레드들이 더이상 필요하지 않을 때 해제하는데 사용한다.

 


이 글은 Coroutines 공식 문서를 번역한 글입니다.

 

원문 : Coroutine context and dispatchers - Jumping between threads

원문 최종 수정 :  2022년 6월 27일

 


Context 내부의 Job

Coroutines의 Job은 Context의 구성요소이고, coroutineContext[Job]*1 표현식으로부터 가져올 수 있다. 

 

fun main() = runBlocking<Unit> {
    println("My job is ${coroutineContext[Job]}")    
}

📌 전체 코드는 이곳에서 확인할 수 있습니다.

 

디버그 모드에서 출력은 다음과 같다.

 

My job is "coroutine#1":BlockingCoroutine{Active}@6d311334

 

CoroutineScope의 isActive는 coroutineContext[Job]?.isActive == true 를 편리하게 사용하기 위한 축약어*2임을 참고하자.

 


📖 아래 내용은 독자의 이해를 위해 번역자가 추가한 글입니다.

*1. CoroutineContext는 내부 요소들을 Map 형태로 관리한다. Map의 Key값에 Job이 들어가면 CoroutineContext의 Job 구성요소가 추출된다.

public interface Job : CoroutineContext.Element {
    ...
    public companion object Key : CoroutineContext.Key<Job>
    ...
}

 

*2. CoroutineScope.isActive 확장 함수는 CoroutineScope의 coroutineContext에서 Job 객체를 가져온 다음 Job이 isActive인지 체크하며, 만약 null이라면 true를 리턴한다.

@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public val CoroutineScope.isActive: Boolean
    get() = coroutineContext[Job]?.isActive ?: true

 

즉, coroutineScope 내의 CoroutineContext는 하나이며, CoroutineContext 내부에는 CoroutineContext.Key를 상속 받는 Key 값과 해당 Key 값에 대응되는 Value 값으로 구성요소들을 관리한다.  이 구성요소는 Coroutine 현재 실행중인지 판단하는 Job을 포함한다.

 


이 글은 Coroutines 공식 문서를 번역한 글입니다.

 

원문 : Coroutine context and dispatchers - Job in the context

원문 최종 수정 :  2022년 6월 27일

 


Coroutine의 자식들

Coroutine이 다른 Coroutine의 CoroutineScope내에서 실행되면 Context를 CoroutineScope.coroutineContext를 통해 상속 받고 새로운 Coroutine의 Job은 부모 Coroutine의 Job의 자식이 된다. 부모 Coroutine이 취소되면, 자식 Coroutine들 또한 재귀적으로 취소된다.

 

하지만, 부모-자식 관계는 두가지 방법으로 명시적으로 재정의 될 수 있다.

 

  • Coroutine을 실행할 때 두 개의 다른 Scope이 명시적으로 설정하는 경우(예를 들어, GlobalScope.launch), 부모 Scope으로부터 Job을 상속 받지 않는다.*1
  • 새로운 Coroutine을 위해 다른 Job이 Context로 전달되는 경우(아래 예시와 같이) 부모 Scope의 Job을 재정의한다.*2

 

두 경우 모두 실행된 Coroutine은 실행된 Scope에 묶여있지 않고 독립적으로 동작한다.

 

// launch a coroutine to process some kind of incoming request
val request = launch {
    // it spawns two other jobs
    launch(Job()) { 
        println("job1: I run in my own Job and execute independently!")
        delay(1000)
        println("job1: I am not affected by cancellation of the request")
    }
    // and the other inherits the parent context
    launch {
        delay(100)
        println("job2: I am a child of the request coroutine")
        delay(1000)
        println("job2: I will not execute this line if my parent request is cancelled")
    }
}
delay(500)
request.cancel() // cancel processing of the request
println("main: Who has survived request cancellation?")
delay(1000) // delay the main thread for a second to see what happens

📌 전체 코드는 이곳에서 확인할 수 있습니다.

 

코드를 실행한 결과는 다음과 같다.

 

job1: I run in my own Job and execute independently!
job2: I am a child of the request coroutine
main: Who has survived request cancellation?
job1: I am not affected by cancellation of the request

 


📖 아래 내용은 독자의 이해를 위해 번역자가 추가한 글입니다.

*1. 아래와 같이 CoroutineScope(Dispatchers.IO) 를 통해 CoroutineScope을 재정의 한다고 해보자. 

fun main() = runBlocking<Unit> {
    CoroutineScope(Dispatchers.IO).launch {
        ...
    }
}

 

CoroutineScope을 통해 CoroutineContext가 재정의 되면 CoroutineContext는 부모로부터 상속 받지 않게 되어 Job이 없게 된다. 따라서 아래와 같이 context의 Job이 null인 경우 context에 Job을 추가하는 방식으로 CoroutineScope이 만들어진다.

@Suppress("FunctionName")
public fun CoroutineScope(context: CoroutineContext): CoroutineScope =
    ContextScope(if (context[Job] != null) context else context + Job())

 

이로 인해 부모 Coroutine과는 다른 Job을 가지게 되는 것이다.

 

*2. CoroutineContext는 구성요소를 Key-Value 값으로 관리한다. 즉, Key인 Job에 대응하는 Value는 하나뿐이다. 따라서 새로운 Job이 CoroutineContext에 설정되면 Key인 Job에 대응되는 Value값은 새로운 Job이 된다.


이 글은 Coroutines 공식 문서를 번역한 글입니다.

 

원문 : Coroutine context and dispatchers - Children of a coroutine

원문 최종 수정 :  2022년 6월 27일

 


목차로 돌아가기

 

Kotlin Coroutines 공식 문서 한국어 번역본 : Coroutines 한 번에 정리하기

Kotlin Coroutines 공식 문서 번역을 시작하며 Kotlin Coroutines는 Kotlin을 위한 강력한 비동기 솔루션이다. 안드로이드 실무에서는 한동안 높은 점유율을 자랑한 RxJava를 Coroutines가 대체하고 있으며, 새로

simplecode.kr

 

반응형

'공식 문서 번역 > Coroutines 공식 문서' 카테고리의 다른 글

Coroutine Context와 Dispatcher 5편 - Coroutine Scope  (0) 2023.02.24
Coroutine Context와 Dispatcher 4편 - 부모 Coroutine의 책임, Coroutines에 이름 짓기, Context 요소들 결합하기  (0) 2023.02.23
Coroutine Context와 Dispatcher 2편 - Coroutines와 Threads 디버깅 하기 : IntelliJ 사용, 로깅 사용  (0) 2023.02.21
Coroutine Context와 Dispatcher 1편 - Dispatchers와 Threads, Unconfined vs confined dispatcher  (0) 2023.02.20
Coroutines 일시중단 함수 구성하기 2편 - 비동기 스타일 함수, 구조화된 동시성과 async  (0) 2023.02.19


'공식 문서 번역/Coroutines 공식 문서' 카테고리의 다른 글
  • Coroutine Context와 Dispatcher 5편 - Coroutine Scope
  • Coroutine Context와 Dispatcher 4편 - 부모 Coroutine의 책임, Coroutines에 이름 짓기, Context 요소들 결합하기
  • Coroutine Context와 Dispatcher 2편 - Coroutines와 Threads 디버깅 하기 : IntelliJ 사용, 로깅 사용
  • Coroutine Context와 Dispatcher 1편 - Dispatchers와 Threads, Unconfined vs confined dispatcher
심플코드
심플코드
프로그래밍을 어렵지 않게 풀어서 설명하는 기술 블로그
    반응형
  • 심플코드
    심플코드
    심플코드
  • 전체
    오늘
    어제
    • 분류 전체보기 (96)
      • 안드로이드를 위한 Coroutines (2)
      • Unit Testing (19)
      • GitHub Actions (0)
      • 공식 문서 번역 (35)
        • Coroutines 공식 문서 (35)
      • 알고리즘 (7)
        • Kotlin 자료구조 (0)
        • 알고리즘 (7)
        • Kotlin으로 구현하는 자료구조 (0)
      • 코딩 테스트 (0)
      • Deep Learning (0)
      • Machine Learning Math (17)
        • Linear Algebra (17)
      • ML (0)
      • Docker (15)
      • Kubernetes (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 코틀린 코루틴의 정석 책 출간 소식
  • 인기 글

  • 태그

    코루틴
    numpy
    Machine Learning
    코루틴 채널
    Kotlin
    Coroutines Flow
    Coroutines Channel
    unit testing
    TensorFlow
    도커
    코루틴 Flow
    unit test
    컨테이너
    Docker
    junit
    Coroutines
    coroutine
    pytorch
    mockito
    Coroutines Context
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
심플코드
Coroutine Context와 Dispatcher 3편 - Thread 전환 하기, Context 내부의 Job, Coroutine의 자식들
상단으로

티스토리툴바