관리 메뉴

피터의 개발이야기

[kotlin] 코틀린 코루틴의 정석 - 무제한 디스패처(Unconfined Dispatcher) 본문

Programming/Kotlin

[kotlin] 코틀린 코루틴의 정석 - 무제한 디스패처(Unconfined Dispatcher)

기록하는 백앤드개발자 2024. 6. 14. 10:10
반응형

ㅁ 들어가며

 코틀린 코루틴의 정석 책을 보고 정리한 글입니다.

11장 코루틴의 심화 - 무제한 디스패처(Unconfined Dispatcher)

ㅇ 무제한 디스패처는 코루틴을 자신을 실행시킨 스레드에서 바로 실행되도록 한다.

ㅇ 호출된 스레드와 상관없기 때문에 무제한적으로 실행하기 때문에 무제한 디스패처라고 부른다. 

 

자신을 실행 시킨 스레드에서 즉시 실행

fun main() = runBlocking<Unit> {
  val startTime = System.currentTimeMillis()
  // Dispatchers.Unconfined 사용
  launch(Dispatchers.Unconfined) {
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] launch 코루틴 실행 스레드는 ")
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] launch 코루틴이 main에 실행되어 같은 main이 된다.")
  }
}
/*
[main @coroutine#2][실행시간: 2ms] launch 코루틴 실행 스레드는 
[main @coroutine#2][실행시간: 15ms] launch 코루틴이 main에 실행되어 같은 main이 된다.
*/

ㅇ Dispatchers.Unconfined은 자신을 실행 시킨 스레드에서 즉시 실행된다.

fun main() = runBlocking<Unit> {
  val startTime = System.currentTimeMillis()
  println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 메인 작업 실행")
  launch(Dispatchers.Unconfined) { // Dispatchers.Unconfined를 사용해 실행되는 코루틴
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 서브 작업 실행")

  }
  println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 다시 메인 작업 실행")
}
/*
[main @coroutine#1][실행시간: 1ms] 메인 작업 실행
[main @coroutine#2][실행시간: 17ms] 서브 작업 실행
[main @coroutine#1][실행시간: 18ms] 다시 메인 작업 실행
*/

ㅇ 비동기처리를 위해 스레드를 Dispatcher가 할당하지만, 즉시 실행할 경우 마치 동기처리처럼 순서가 보장될 수도 있다.

  ㄴ 실시간으로 바로 이루어야 할 Job에 맞는 Dispatcher이다.

ㅇ 이런 점에서 CoroutineStart.UNDISPATCHED 옵션과 유사하지만 일시 중단 후 다시 할당되는 스레드에 차이가 날 수 있다.

 

CoroutineStart.UNDISPATCHED와 Dispatchers.Unconfined의 차이

fun main() = runBlocking<Unit> {
  val startTime = System.currentTimeMillis()
  println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 메인 작업 실행")
  launch(start = CoroutineStart.UNDISPATCHED) { // CoroutineStart.UNDISPATCHED가 적용된 코루틴
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] CoroutineStart.UNDISPATCHED 작업 실행")
    delay(100L)
    // CoroutineStart.UNDISPATCHED은 자신이 실행되는 CoroutineDispatcher 객체를 사용한다.
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] CoroutineStart.UNDISPATCHED 작업 재할당해도 나는 main이다.")
  }.join()
  launch(Dispatchers.Unconfined) { // Dispatchers.Unconfined를 사용해 실행되는 코루틴
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] Dispatchers.Unconfined 작업 실행")
    delay(100L)
    // Dispatchers.Unconfined는 자신을 재개시킨 스레드가 할당된다.
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] Dispatchers.Unconfined 작업 재할당하면...")
  }
  println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 다시 메인 작업 실행")
}
/*
[main @coroutine#1][실행시간: 0ms] 메인 작업 실행
[main @coroutine#2][실행시간: 18ms] CoroutineStart.UNDISPATCHED 작업 실행
[main @coroutine#2][실행시간: 125ms] CoroutineStart.UNDISPATCHED 작업 재할당해도 나는 main이다.
[main @coroutine#3][실행시간: 127ms] Dispatchers.Unconfined 작업 실행
[main @coroutine#1][실행시간: 128ms] 다시 메인 작업 실행
[kotlinx.coroutines.DefaultExecutor @coroutine#3][실행시간: 232ms] Dispatchers.Unconfined 작업 재할당하면...
*/

ㅇ CoroutineStart.UNDISPATCHED은 자신이 실행되는 CoroutineDispatcher 객체를 사용한다.
ㅇ Dispatchers.Unconfined는 자신을 재개시킨 스레드가 할당된다.

 

중단 후 재개하는 스레드에서 실행

fun main() = runBlocking<Unit> {
  val startTime = System.currentTimeMillis()
  println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 메인 작업 실행")
  launch(Dispatchers.Unconfined) { // Dispatchers.Unconfined를 사용해 실행되는 코루틴
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 서브 작업 실행")
    delay(100L)
    println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 서브 작업 실행")

  }
  println("[${Thread.currentThread().name}][${getRunTime(startTime)}] 다시 메인 작업 실행")
}
/*
[main @coroutine#1][실행시간: 0ms] 메인 작업 실행
[main @coroutine#2][실행시간: 14ms] 서브 작업 실행
[main @coroutine#1][실행시간: 19ms] 다시 메인 작업 실행
[kotlinx.coroutines.DefaultExecutor @coroutine#2][실행시간: 120ms] 서브 작업 실행
*/

ㅇ 위의 코드에 delay를 추가하여 스레드 재할당을 유도하였을 때 kotlinx.coroutines.DefaultExecutor가 할당되었다.

ㅇ Dispatchers.Unconfined은 일시 중단 후 재개 시키는 스레드에서 즉시 실행된다.

ㅇ 이로 인해 Dispatchers.Unconfined를 사용해 실행된 코루틴은 동작을 예측하기 어렵다.

 

ㅁ 함께 보면 좋은 사이트

 조세영 - 코틀린 코루틴의 정석

반응형
Comments