在官方演员范例文档的kotlinlang.org文档中,一个参与者被启动了10万次,这只是增加了参与者内部的一个计数器。然后向参与者发送一个get请求,并在响应中以正确的数量(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协同器在多个线程上执行会发生什么?如果协同线在不同的线程上运行,那么参与者中的变量“计数器”可能容易受到争用条件的影响,不是吗?
示例:一个线程运行一个coroutine,这个线程在通道上接收,然后在另一个线程上,coroutine可以接收到,它们都试图同时更新计数器变量,从而错误地更新了变量。
在代码示例后面的文本中
参与者本身在什么上下文中执行(对于正确性而言)并不重要。参与者是协同线,协同线是按顺序执行的,因此将状态限制到特定的协同线可以解决共享可变状态的问题。
我很难理解这一点。有人能详细说明这到底意味着什么,以及为什么种族条件不存在或发生。当我运行这个例子时,我看到所有的协同线都运行在同一个主线程上,所以我无法证明我关于种族条件的理论。
发布于 2019-02-02 07:35:54
“男演员推出10万次”
不,actor
是在第1次发射的,就在这条线上
val counterActor = counterActor()
然后,它接收100000条消息,来自在不同线程上并行工作的100个协同服务。但是它们不直接增加变量counter
,它们只向参与者的输入消息队列添加消息。实际上,这个在kotlinx.coroutines
库中实现的操作是线程安全的。
https://stackoverflow.com/questions/54490764
复制相似问题