Sleep Instead Of Delay

ID

kotlin.sleep_instead_of_delay

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Kotlin

Tags

concurrency, reliability

Description

Reports Thread.sleep(…​) calls that occur inside a suspend function or inside a coroutine builder lambda (launch, async, runBlocking, withContext, coroutineScope, supervisorScope, flow, …​).

Thread.sleep parks the OS thread the coroutine is currently dispatched on. Because coroutines share a small pool of dispatcher threads, a single blocking sleep can stall every coroutine on that dispatcher until the timeout elapses.

Rationale

// Bad — blocks the dispatcher thread
suspend fun load() {
    Thread.sleep(1000)
}

scope.launch {
    Thread.sleep(1000)
}

In a server environment the I/O dispatcher typically has 64 threads. Sixty-four coroutines that all call Thread.sleep will fully saturate the dispatcher, and every other I/O coroutine queues behind them.

Remediation

Use kotlinx.coroutines.delay. It suspends only the calling coroutine and returns the thread to the dispatcher.

suspend fun load() {
    delay(1000)
}

scope.launch {
    delay(1000)
}

Exceptions

Receiver resolution is used when available — only calls whose receiver resolves to java.lang.Thread are flagged. Calls outside any coroutine context are not reported.