Using actors in Kotlin - a concurrent play in one act
Tags: kotlin, coroutines, actors, concurrency
Published: 2019-10-01 17:46:51

---
title: Using actors in Kotlin - a concurrent play in one act
published: true
tags: kotlin, coroutines, actors, concurrency
canonical_url: 
cover_image: https://thepracticaldev.s3.amazonaws.com/i/fgztqrn76j1ses9tr5e7.jpg
---

In february this year I already wrote about [Kotlin coroutines and their usage in JavaFX applications](/domnikl/kotlin-coroutines-and-javafx-threads-26od/) and today I want to explore coroutines even further and talk about them in the context of actors.

## Why not Threads?

A modern software system has to manage a lot of different tasks at the same time. User requests coming in via web interfaces, GUIs and other channels need to be handled while there is background work to be done. Traditionally this has been the domain of operation system threads that the application spawned and provided with work.

![Photo by Héctor J. Rivas on Unsplash](https://thepracticaldev.s3.amazonaws.com/i/9xbs2na48kvzncjsh9cd.jpg "Photo by Héctor J. Rivas on Unsplash")Photo by Héctor J. Rivas

But as you may know, threading is error-prone and not easily done right when it comes to mutating state in an complex application (if you don’t you should read [Why Threads Are A Bad Idea (for most purposes)](https://web.stanford.edu/~ouster/cgi-bin/papers/threads.pdf)). With `coroutines`, there is a lightweight and simple alternative to threads in Kotlin that follows the approach of [Communicating Sequential Processes](https://de.wikipedia.org/wiki/Communicating_Sequential_Processes). It’s the same idea that inspired Go’s goroutines:

> Do not communicate by sharing memory; instead, share memory by communicating. - [Effective Go](https://golang.org/doc/effective_go.html#sharing)

Kotlin achieves that by providing the concept of a `Channel`, which basically is a [Queue that uses suspending functions](https://kotlinlang.org/docs/reference/coroutines/channels.html#channel-basics). Using coroutines and channels, we can build a system that encapsulate mutable state in a manner that do not need any locks and synchronization and instead leverage a protocol of messages to handle concurrent updates of that state.

## The actor model

![Photo by Avel Chuklanov on Unsplash](https://thepracticaldev.s3.amazonaws.com/i/ikohisoqozn1bfpcrwtg.jpg "Photo by Avel Chuklanov on Unsplash")Photo by Avel Chuklanov

Such a model is called an actor. It is not a new concept, instead it has been around for years and is the underlying concept of Erlang and can also be used in Java and Scala using Akka. In [How does keeing state in Elixir work?](https://domnikl.github.io/2018/03/how-does-keeping-state-in-elixir-work/) I built an actor in Elixir even though the concept is not officially called an ‘actor’ in the BEAM world, but `gen_server` instead.

Actors come in many sizes and they can do a wide variety of tasks, but they all share the same properties:

- they keep internal state
- they are running concurrently
- their state can be manipulated through messages only
- they receive messages in a channel that is called a ‘mail box’
- they process messages sequentially

## Don’t try this at home!

Ok, this might be a bit exaggerated, but there is a need to warn you. Precisely to warn you about the state of implementation for the `actor()` function. As of writing it is a very simple API to create an actor but this is about to change in [future releases of kotlinx.coroutines](https://github.com/Kotlin/kotlinx.coroutines/issues/87).

## basic counter example

So what does an actor in Kotlin look like? Let’s have a look.

First of all, we need to define messages we can send to the actor. In this simple example, the actor stores a counter that can be incremented by arbitrary integer values using `Message.Increment` and the current value can be requested by `Message.GetValue`.

To send data back to the requesting code, we use a `CompletableDeferred` here.

```kotlin
sealed class Message {
    class Increment(val value: Int) : Message()
    class GetValue(val deferred: CompletableDeferred<Int>) : Message()
}
```

Next up, we define the actor named `basicActor` itself. It needs to be defined as an extension function to `CoroutineScope` as it will launch a coroutine to run in. It runs a simple `for` loop to get messages from the channel that will run until anyone closes the channel. The handling of the messages is rather straight forward.

```kotlin
fun CoroutineScope.basicActor() = actor<Message> {
    var counter = 0

    for (message in channel) {
        when(message) {
            is Message.Increment -> counter += message.value
            is Message.GetValue -> message.deferred.complete(counter)
        }
    }
}
```

That’s it! But to use it, you also have to define a client that sends messages to the actor. Here’s the code:

```kotlin
fun main() = runBlocking<Unit> {
    val channel = basicActor()

    channel.send(Message.Increment(1))
    channel.send(Message.Increment(2))

    val deferred = CompletableDeferred<Int>()

    channel.send(Message.GetValue(deferred))

    println(deferred.await()) // prints "3"

    channel.close()
}
```

In `main` we define a `CoroutineScope` by using `runBlocking()` which is then used to launch the actor in and send messages. `channel.close()` will then cause the actor to complete. Without it, the actor will keep the program running infinitely, which may be a desired state in a typically server situation.

## Conclusion

Actors are an easy concept that can help to remove the hassle of concurrent computing. They are still experimental in `kotlinx.coroutines` but it’s a first step in the direction and I am curious of the developments and as a long-time fan of Erlang and Elixir I appreciate actors and would happily welcome them as a stable component of Kotlin coroutines.