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.