Kotlin 协程是否提供任何“发生之前”保证?
例如,在这种情况下,写入 mutableVar
和随后在(可能)其他线程上读取之间是否存在“发生之前”保证:
suspend fun doSomething() {
var mutableVar = 0
withContext(Dispatchers.IO) {
mutableVar = 1
}
System.out.println("value: $mutableVar")
}
编辑:
也许额外的例子可以更好地阐明问题,因为它更符合 Kotlin 风格(除了可变性)。此代码线程安全吗:
suspend fun doSomething() {
var data = withContext(Dispatchers.IO) {
Data(1)
}
System.out.println("value: ${data.data}")
}
private data class Data(var data: Int)
最佳答案
您编写的代码可以对共享状态进行三种访问:
var mutableVar = 0 // access 1, init
withContext(Dispatchers.IO) {
mutableVar = 1 // access 2, write
}
System.out.println("value: $mutableVar") // access 3, read
这三个访问是严格按顺序排序的,它们之间没有并发性,您可以放心,Kotlin 的基础设施会在移交给 IO 时负责建立 happens-before 边缘
线程池并返回到您的调用协程。
这是一个可能看起来更有说服力的等效示例:
launch(Dispatchers.Default) {
var mutableVar = 0 // 1
delay(1)
mutableVar = 1 // 2
delay(1)
println("value: $mutableVar") // 3
}
由于 delay
是一个可挂起的函数,并且由于我们使用的是由线程池支持的 Default
调度程序,因此第 1、2 和 3 行可能各自执行在不同的线程上。因此,您关于 happen-before 保证的问题同样适用于本示例。另一方面,在这种情况下(我希望)完全明显的是该代码的行为与顺序执行的原则一致。
Roman Elizarov,Kotlin Coroutines 的主要作者,在 blog post 中提出了同样的观点。 。相关引用:
Even though a coroutine in Kotlin can execute on multiple threads, it is just like a thread from a standpoint of mutable state. No two actions in the same coroutine can be concurrent.
关于Kotlin 协程 "happens-before"保证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58518783/