Simple&Natural

Coroutine IO Dispatcher의 Thread number가 최대 Thread 갯수를 초과하는 이슈 본문

안드로이드(Android)/이슈 및 해결

Coroutine IO Dispatcher의 Thread number가 최대 Thread 갯수를 초과하는 이슈

Essense 2020. 9. 27. 06:19
728x90

[문제]

 

공식문서에 의하면 IO Dispatcher가 사용하는 스레드 풀의 최대 스레드 갯수는 64개를 넘지 않는다.

 

하지만 내 노트북에서 실험한 결과 간혹 스레드 번호가 64를 초과하여 찍힐 때가 있었다.

같은 코드를 kotlin.org에서 제공하는 PlayGround 에서 찍어보면 또 전혀 문제가 없다.

 

혹시 기존의 64개 스레드가 모두 점유되고 있으면 추가로 스레드를 더 생성하는 건지 궁금하여

자료를 찾아보아도 딱히 관련된 내용이 없었고 공식 Github에 이슈를 체크해도 딱히 답변이 없는 상황. 

 

 

 

repeat(500) {
    CoroutineScope(Dispatchers.IO).launch {
        println(Thread.currentThread().name)
    }
}

 

 

...

DefaultDispatcher-worker-18
DefaultDispatcher-worker-46
DefaultDispatcher-worker-17
DefaultDispatcher-worker-47
DefaultDispatcher-worker-69
DefaultDispatcher-worker-64
DefaultDispatcher-worker-66
DefaultDispatcher-worker-67
DefaultDispatcher-worker-68
DefaultDispatcher-worker-41

...

 

 

 

[해결]

추가적으로 공식 깃허브에 이슈를 올린 결과 다음과 같은 답변이 왔다.

 


Thanks for pointing it out, I'll rephrase the doc a bit.

Dispatchers.IO shares underlying threadpool with Dispatchers.Default, so the number of simultaneous threads is 64 + #CORES_SIZE. In your particular example, underlying threadpool starts compensating all 64 IO threads with a few threads for potential tasks in Dispatchers.Default


IO Dispatcher는 Default Dispatcher와 스레드 풀을 공유한다. 즉, 기존의 CPU 코어 만큼의 스레드(Default)에 64개의 스레드(IO)가 추가되므로 내 경우 최대 76개의 스레드가 생성되는 것이다.

 

다만 동시에 돌릴 수 있는 최대 스레드는 64개로 유지된다.

 

또한 아래 코드를 이용해 확인해보면 max thread 갯수는 64가 나온다.

 

@Test
    fun test() {
        class Counter {
            private var current=0
            private var max=0
            fun addOne() {
                synchronized(this) {
                    current++
                    max = Math.max(max,current)

                }
            }
            fun subOne() {
                synchronized(this) {
                    current--
                }
            }
            fun getMax() = max
        }

        val counter = Counter()

        val jobs = (0..500).map {
            CoroutineScope(Dispatchers.IO).launch {
                counter.addOne()
                Thread.sleep(100)
                counter.subOne()
            }
        }
        var done = false
        while(!done) {
            val j = jobs.find{it.isActive}
            if( j == null) {
                done = true
            } else {
                Thread.sleep(100)
            }
        }

        println("max = ${counter.getMax()}")
    }

 

 

 

 

 

 

 

참고자료)

stackoverflow.com/questions/64074289/why-does-io-dispatchers-create-more-than-64-thread-in-kotlin-corotines/64096221?noredirect=1#comment113359228_64096221

 

Why does IO Dispatchers create more than 64 thread in Kotlin corotines?

As I understood, Maximum number of threads that can be created by Dispatchers.IO is 64, but my result is a little bit tricky. this is my code. repeat(500) { CoroutineScope(Dispatchers.IO).launc...

stackoverflow.com

github.com/Kotlin/kotlinx.coroutines/issues/2272

 

IO Dispatcher creates more than 64 threads · Issue #2272 · Kotlin/kotlinx.coroutines

Annotation describes IO Dispatcher like this, It defaults to the limit of 64 threads or the number of cores (whichever is larger). As I understood, Maximum number of threads that can be created by ...

github.com

 

 

728x90