From 8870c584d3738289102fb57066bbb5d0eb9fb905 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 8 Dec 2011 14:59:39 +0100 Subject: [PATCH 1/2] Clarifying some do's and dont's on Actors in the jmm docs --- akka-docs/general/jmm.rst | 40 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/akka-docs/general/jmm.rst b/akka-docs/general/jmm.rst index 74ef84e752..fd7cab5eec 100644 --- a/akka-docs/general/jmm.rst +++ b/akka-docs/general/jmm.rst @@ -59,4 +59,42 @@ How these rules are realized in Akka is an implementation detail and can change even depend on the used configuration. But they will build on the other JMM rules like the monitor lock rule or the volatile variable rule. This means that you, the Akka user, do not need to worry about adding synchronization to provide such a "happens before" relation, because it is the responsibility of Akka. So you have your hands free to deal with your -business logic, and the Akka framework makes sure that those rules are guaranteed on your behalf. \ No newline at end of file +business logic, and the Akka framework makes sure that those rules are guaranteed on your behalf. + +Actors and shared mutable state +------------------------------- + +Since Akka runs on the JVM there are still some rules to be followed. + +* Closing over internal Actor state and exposing it to other threads + +.. code-block:: scala + + class MyActor extends Actor { + var state = ... + def receive = { + case _ => + //Wrongs + + // Very bad, shared mutable state, + // will break your application in weird ways + Future { state = NewState } + + // Very bad, "sender" changes for every message, + // shared mutable state bug + Future { expensiveCalculation(sender) } + + //Rights + + // Completely safe, "self" is OK to close over + // and it's an ActorRef, which is thread-safe + Future { expensiveCalculation() } onComplete { f => self ! f.value.get } + + // Completely safe, we close over a fixed value + // and it's an ActorRef, which is thread-safe + val currentSender = sender + Future { expensiveCalculation(currentSender) } + } + } + +* Messages **should** be immutable, this is to avoid the shared mutable state trap. \ No newline at end of file From c2d9e7064535c9e32aca6940a5d3aec544550caf Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 8 Dec 2011 15:16:04 +0100 Subject: [PATCH 2/2] Fixing indentation and adding another common pitfall --- akka-docs/general/jmm.rst | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/akka-docs/general/jmm.rst b/akka-docs/general/jmm.rst index fd7cab5eec..a84bad2dd2 100644 --- a/akka-docs/general/jmm.rst +++ b/akka-docs/general/jmm.rst @@ -70,31 +70,32 @@ Since Akka runs on the JVM there are still some rules to be followed. .. code-block:: scala - class MyActor extends Actor { - var state = ... + class MyActor extends Actor { + var state = ... def receive = { - case _ => - //Wrongs + case _ => + //Wrongs // Very bad, shared mutable state, // will break your application in weird ways - Future { state = NewState } - + Future { state = NewState } + anotherActor ? message onResult { r => state = r } + // Very bad, "sender" changes for every message, // shared mutable state bug - Future { expensiveCalculation(sender) } + Future { expensiveCalculation(sender) } - //Rights + //Rights // Completely safe, "self" is OK to close over // and it's an ActorRef, which is thread-safe - Future { expensiveCalculation() } onComplete { f => self ! f.value.get } - + Future { expensiveCalculation() } onComplete { f => self ! f.value.get } + // Completely safe, we close over a fixed value // and it's an ActorRef, which is thread-safe - val currentSender = sender - Future { expensiveCalculation(currentSender) } + val currentSender = sender + Future { expensiveCalculation(currentSender) } } - } + } * Messages **should** be immutable, this is to avoid the shared mutable state trap. \ No newline at end of file