ENIGMA AI
ENIGMA AI
Kotlin Сложный

Как корутины работают под капотом в Kotlin?

Корутины Kotlin под капотом

Ключевая концепция: CPS + State Machine

CPS (Continuation Passing Style):
Компилятор преобразует suspend-функции в функции с Continuation.

Что происходит при компиляции:

// Исходный код
suspend fun fetchUser(): User {
    val token = getToken()      // suspend point 1
    val user = loadUser(token)  // suspend point 2
    return user
}

// После компиляции (псевдокод)
fun fetchUser(continuation: Continuation<User>): Any? {
    val sm = continuation as? FetchUserSM
        ?: FetchUserSM(continuation)

    when (sm.label) {
        0 -> {
            sm.label = 1
            val result = getToken(sm)
            if (result == COROUTINE_SUSPENDED)
                return COROUTINE_SUSPENDED
            sm.token = result as String
        }
        1 -> {
            sm.label = 2
            val result = loadUser(sm.token, sm)
            if (result == COROUTINE_SUSPENDED)
                return COROUTINE_SUSPENDED
            sm.user = result as User
        }
        2 -> {
            return sm.user
        }
    }
}

State Machine:

class FetchUserSM(
    completion: Continuation<User>
) : ContinuationImpl(completion) {
    var label = 0
    var token: String? = null
    var user: User? = null

    override fun invokeSuspend(result: Result<Any?>): Any? {
        // Обработка результата и продолжение
    }
}

Continuation Interface:

interface Continuation<in T> {
    val context: CoroutineContext
    fun resumeWith(result: Result<T>)
}

Dispatcher и переключение потоков:

// Dispatchers.Default
// Использует ForkJoinPool

// Dispatchers.IO
// Отдельный пул для блокирующих операций

// Dispatchers.Main
// Main thread (Android Handler)

withContext(Dispatchers.IO) {
    // Continuation сохраняется
    // Код выполняется в IO пуле
    // resumeWith() возвращает в исходный поток
}

Suspend vs Block:

// suspend — освобождает поток
suspend fun delay(ms: Long) {
    // Поток свободен для других корутин
}

// block — занимает поток
fun Thread.sleep(ms: Long) {
    // Поток заблокирован
}

Почему это эффективно:

  1. Нет создания потоков — используются существующие
  2. Лёгкие объекты — только state machine
  3. Кооперативная многозадачность — явные точки приостановки
  4. Структурированный параллелизм — иерархия coroutine scopes

Похожие вопросы

Готовитесь к собеседованию?

ENIGMA AI — невидимый ИИ-помощник для технических интервью

Попробовать бесплатно
Все вопросы