我决定深入研究Kotlin协程。我对可见度有一些疑问。我知道在没有ContinuationInterceptor
的情况下,可能会由不同的线程执行同一协程的不同部分。
如何保证在暂停后新线程对协程内部状态具有正确的可见性?
例如:
suspend fun doPost(customRatings : Map<String, Int>) : Int {...}
fun postRatings_1() {
GlobalScope.launch {
val mutableMap : MutableMap<String, Int> = mutableMapOf()
mutableMap["Apple"] = 1
mutableMap["Banana"] = 2
// ...
val postId = doPost(mutableMap)
// How am I guaranteed to see the two entries here ?
println("posted ${mutableMap} with id ${postId}")
}
}
类似地,当新的协程启动时
fun postRatings_2() {
val mutableMap : MutableMap<String, Int> = mutableMapOf()
mutableMap["Apple"] = 1
mutableMap["Banana"] = 2
GlobalScope.launch {
// How am I guaranteed to see the two entries here ?
val postId = doPost(mutableMap)
//...
}
在这两种情况下,两个(现有)线程之间共享一些可变状态。
我正在寻找“先发生”规则,该规则保证可变状态将被两个线程正确可见。
答案 0 :(得分:5)
我正在寻找“先发生”规则,该规则保证可变状态将被两个线程正确可见。
保证很容易实现:例如,如果您的调度程序基于Java线程池,则线程池本身已经提供了此保证。 executor.submit()
之前的代码调用提交的代码
即使您使用称为Dispatchers.Unconfined
的null调度程序,它只是在碰巧调用continuation.resume(result)
的任何线程上恢复协程,您仍然会得到 happens-before 因为调用回调的基础框架对此提供了保证。
在编写自定义损坏的Dispatcher
实现以弄乱顺序时,您必须走得很远。