【发布时间】:2021-10-03 03:23:53
【问题描述】:
在尝试使用 kotlin 协程时,我遇到了一个我没想到会发生死锁的情况。
我将代码简化为以下显示问题的最小代码示例:
@Test
fun deadlockTest() {
runBlocking {
val job = launch {
runBlocking {
println("await cancellation")
awaitCancellation()
}
}
println("launched job")
delay(100)
println("waited a bit")
job.cancelAndJoin()
println("canceled and joined")
}
assertTrue(true)
}
结果是
launched job
await cancellation
waited a bit
它永远不会超出job.cancelAndJoin,好像有一些死锁一样。
如果我将代码稍微更改为以下内容:
@Test
fun fixedDeadlockTest() {
runBlocking {
val job = launch {
withContext(Dispatchers.Default) { // <-- this is the only difference
println("awaiting cancellation")
awaitCancellation()
}
}
println("launched job")
delay(100)
println("waited a bit")
job.cancelAndJoin()
println("canceled and joined")
}
assertTrue(true)
}
一切正常,所有行都被打印出来,测试完成。
问题是:为什么这段代码会导致死锁,将一个 runBlocking 放在另一个 runBlocking 的启动中是不是一种不好的做法? (即在您的代码中永远不要使用 runBlocking,直到您从非协程范围内实际启动协程?)
我使用了以下版本:
- kotlin 多平台 1.4.32
- kotlinx-coroutines-core 版本 1.5.0-native-mt
【问题讨论】:
标签: kotlin kotlin-coroutines kotlin-multiplatform