Akka and the Java Memory Model

Akka and the Java Memory Model

A major benefit of using the Typesafe Platform, including Scala and Akka, is that it simplifies the process of writing concurrent software. This article discusses how the Typesafe Platform, and Akka in particular, approaches shared memory in concurrent applications.

The Java Memory Model


  • a thread observing 'impossible' behavior of other threads, caused by instructions not being executed in the order expected: an instruction reordering problem.

With the implementation of JSR 133 in Java 5, a lot of these issues have been resolved. The JMM is a set of rules based on the "happens-before" relation, which constrain when one memory access must happen before another, and conversely, when they are allowed to happen out of order. Two examples of these rules are:



Actors and the Java Memory Model


  • if a message is sent to an actor (e.g. by another actor). In most cases messages are immutable, but if that message is not a properly constructed immutable object, without a "happens before" rule, it would be possible for the receiver to see partially initialized data structures and possibly even values out of thin air (longs/doubles).
  • if an actor makes changes to its internal state while processing a message, and accesses that state while processing another message moments later. It is important to realize that with the actor model you don't get any guarantee that the same thread will be executing the same actor for different messages.

To prevent visibility and reordering problems on actors, Akka guarantees the following two "happens before" rules:



In layman's terms this means that changes to internal fields of the actor are visible when the next message is processed by that actor. So fields in your actor need not be volatile or equivalent.


Futures and the Java Memory Model

The completion of a Future "happens before" the invocation of any callbacks registered to it are executed.



STM and the Java Memory Model

Akka's Software Transactional Memory (STM) also provides a "happens before" rule:




Actors and shared mutable state


  • Closing over internal Actor state and exposing it to other threads
class MyActor extends Actor {
 var state = ...
 def receive = {
    case _ =>

    // Very bad, shared mutable state,
    // will break your application in weird ways
      Future { state = NewState }
      anotherActor ? message onSuccess { r => state = r }

    // shared mutable state bug
      Future { expensiveCalculation(sender()) }


    // and it's an ActorRef, which is thread-safe

    // Completely safe, we close over a fixed value
    // and it's an ActorRef, which is thread-safe
      val currentSender = sender()
      Future { expensiveCalculation(currentSender) }