akka-docs/src/main/paradox/general/jmm.md
A major benefit of using the Lightbend Platform, including Scala and Akka, is that it simplifies the process of writing concurrent software. This article discusses how the Lightbend Platform, and Akka in particular, approaches shared memory in concurrent applications.
Prior to Java 5, the Java Memory Model (JMM) was ill defined. It was possible to get all kinds of strange results when shared memory was accessed by multiple threads, such as:
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:
Although the JMM can seem complicated, the specification tries to find a balance between ease of use and the ability to write performant and scalable concurrent data structures.
With the Actors implementation in Akka, there are two ways multiple threads can execute actions on shared memory:
To prevent visibility and reordering problems on actors, Akka guarantees the following two "happens before" rules:
@@@ note
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.
@@@
Both rules only apply for the same actor instance and are not valid if different actors are used.
The completion of a Future "happens before" the invocation of any callbacks registered to it are executed.
We recommend not to close over non-final fields (final in Java and val in Scala), and if you do choose to close over non-final fields, they must be marked volatile in order for the current value of the field to be visible to the callback.
If you close over a reference, you must also ensure that the instance that is referred to is thread safe. We highly recommend staying away from objects that use locking, since it can introduce performance problems and in the worst case, deadlocks. Such are the perils of synchronized.
<a id="jmm-shared-state"></a>
Since Akka runs on the JVM there are still some rules to be followed.
Most importantly, you must not close over internal Actor state and exposing it to other threads:
Scala : @@snip SharedMutableStateDocSpec.scala { #mutable-state }
Java : @@snip DistributedDataDocTest.java { #mutable-state }