Kotlin协程中的可见性

时间:2019-11-17 14:54:08

标签: multithreading kotlin concurrency kotlin-coroutines

我决定深入研究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)
            //...
        }

在这两种情况下,两个(现有)线程之间共享一些可变状态。

我正在寻找“先发生”规则,该规则保证可变状态将被两个线程正确可见。

1 个答案:

答案 0 :(得分:5)

  

我正在寻找“先发生”规则,该规则保证可变状态将被两个线程正确可见。

保证很容易实现:例如,如果您的调度程序基于Java线程池,则线程池本身已经提供了此保证。 executor.submit()之前的代码调用提交的代码之前,而该代码依次观察相关未来的完成的代码 happens-before

即使您使用称为Dispatchers.Unconfined的null调度程序,它只是在碰巧调用continuation.resume(result)的任何线程上恢复协程,您仍然会得到 happens-before 因为调用回调的基础框架对此提供了保证。

在编写自定义损坏的Dispatcher实现以弄乱顺序时,您必须走得很远。