Dmytro Serdiuk
04/01/2021, 4:10 PMfun main() = runBlocking<Unit> {
val counter = counterActor() // create the actor withContext(Dispatchers.Default) {
massiveRun {
counter.send(IncCounter)
}
}
// send a message to get a counter value from an actor
val response = CompletableDeferred<Int>()
counter.send(GetCounter(response))
println("Counter = ${response.await()}")
counter.close() // shutdown the actor
}
Actor is more efficient than locking under load, because in this case it always has work to do and it does not have to switch to a different context at all.
How to understand it?And how is it efficient than locks?gildor
04/03/2021, 6:24 AMDmytro Serdiuk
04/04/2021, 1:44 PMgildor
04/04/2021, 3:26 PMDmytro Serdiuk
04/04/2021, 3:27 PMgildor
04/04/2021, 3:28 PMDmytro Serdiuk
04/04/2021, 3:29 PMgildor
04/05/2021, 12:59 AMDmytro Serdiuk
04/05/2021, 9:47 AMval mutex = Mutex()
var counter = 0
fun main() = runBlocking {
withContext(Dispatchers.Default) {
massiveRun {
// protect each increment with lock
mutex.withLock {
counter++
}
}
}
println("Counter = $counter")
}
In this case we have Dispatchers.Default that are bound to CPU threads, so the counter will be incremented in different threads, but it doesn’t mean that there would be a context switch, as we are bound to CPU cores.
In case of actors, there would be the same workers in Dispatchers.Default + one more coroutine in main dispatchers that will be as a queue.
Am I right or could you give me more details please. Anyway, thank yougildor
04/08/2021, 7:38 AMDmytro Serdiuk
04/08/2021, 9:33 PM