在不同线程上运行时,kotlin中的参与者如何工作?

时间:2019-02-02 06:52:53

标签: kotlin concurrency actor kotlinx.coroutines

在kotlinlang.org官方文档的actor example中,一个actor被启动了100 000次,这仅增加了actor内部的计数器。然后获取请求被发送给演员和计数器与正确量(100 000)的响应发送。

这是代码:

// The messages
sealed class CounterMsg
object IncCounter : CounterMsg() // one-way message to increment counter
class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // a two-way message to get the counter

// The actor
fun CoroutineScope.counterActor() = actor<CounterMsg> { 
    var counter = 0 // actor state
    for (msg in channel) { // iterate over incoming messages
        when (msg) {
            is IncCounter -> counter++
            is GetCounter -> msg.response.complete(counter)
        }
    }
}

fun main() {
    runBlocking {
        val counterActor = counterActor()
        GlobalScope.massiveRun {
            counterActor.send(IncCounter) // run action 100000 times
        }
        val response = CompletableDeferred<Int>()
        counterActor.send(GetCounter(response))
        println("Counter = ${response.await()}")
        counterActor.close()
    }
}

我很难理解如果将counterActor协程在多个线程上执行会发生什么情况?如果协程将在不同的线程上运行,则参与者中的变量'counter'可能会受到竞赛条件的影响,

示例:一个线程运行一个协程,该协程在通道上接收,然后在另一个线程上,一个协程可以接收,并且它们都尝试同时更新计数器变量,从而错误地更新了变量。

在代码示例后的文本中

  

(正确性)执行者本身在什么上下文中执行无关紧要。执行者是协程,协程是顺序执行的,因此,将状态限制为特定协程可以解决该问题。共享可变状态的问题。

我很难理解这一点。有人可以详细说明这到底意味着什么,以及为什么种族状况没有发生。当我运行示例时,我看到所有协程都在同一主线程上运行,因此无法证明我的竞争条件理论。

1 个答案:

答案 0 :(得分:2)

“演员被发射了10万次”

否,actor在该行刚启动1次

val counterActor = counterActor()

然后,它从在不同线程上并行工作的100个协程接收100000条消息。但是它们不会直接增加变量counter,它们只会将消息添加到参与者的输入消息队列中。的确,在kotlinx.coroutines库中实现的此操作是线程保存的。