Как работают актеры в котлине, когда бегают по разным потокам? - PullRequest
0 голосов
/ 02 февраля 2019

В примере актер из официальной документации kotlinlang.org, актер запускается 100 000 раз, что просто увеличивает счетчик внутри актера.Затем актер получает запрос на получение и счетчик отправляет в ответе правильную сумму (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 в субъекте потенциально будет восприимчива к условию race , не так ли?

Пример: один поток запускает сопрограмму, и этополучает по каналу, а затем в другом потоке может получить сопрограмму, и они оба пытаются обновить переменную счетчика одновременно, что приводит к неправильному обновлению переменной.

В тексте, следующем за примером кода

Неважно (для правильности), в каком контексте выполняется сам актер. Актер является сопрограммой, а сопрограмма выполняется последовательно, , так что ограничение состояния конкретной подпрограммой работаеткак решение проблемы общего изменчивого состояния .

Мне трудно понять это.Может ли кто-нибудь уточнить, что именно это означает, и почему условия расы не возникают.Когда я запускаю пример, я вижу, что все сопрограммы работают в одном и том же главном потоке, поэтому я не могу доказать свою теорию состояния гонки.

1 Ответ

0 голосов
/ 02 февраля 2019

«Актер запускается 100 000 раз»

Нет, actor запускается ровно 1 раз, по строке

val counterActor = counterActor()

Затем он получает 100000 сообщений от 100 работающих сопрограмм.параллельно на разные темы.Но они не увеличивают переменную counter напрямую, они только добавляют сообщения в очередь входных сообщений субъекта.Действительно, эта операция, реализованная в библиотеке kotlinx. coroutines, сделана поточно-ориентированной.

...