This document discusses actor-based concurrency and the Akka framework. It explains that actors are lightweight processes that communicate asynchronously by message passing rather than by sharing memory. This allows for high levels of concurrency. The document provides an example demonstrating how to define actor messages and behaviors in Akka to implement a simple counter actor. It also discusses some antipatterns to avoid, such as directly modifying actor state from outside the actor.
2. Benefit of actor in one sentence
C vs Java:
You can use memory without having to free
memory.
Thread vs actor:
You can use concurrency without having to
create threads.
Don't communicate by sharing memory;
share memory by communicating.
3. Actor model
● Actor =
states +
mailbox +
behaviors (msg handlers)
http://www.cs.tsukuba.ac.jp/~yas/c
s/csys-2013/2013-12-03/
● From outside, can’t manipulate actors directly.
● To interact with an actor, must send msgs to it.
● Each actor has a mailbox, msgs are put to mailbox, and
processed one by one. ← An actor is like a single
threaded process; it doesn’t do more than one thing at a
time.
4. Concurrency: Actor vs Thread
Thread:
● Heavy weight: Can only create not too many threads;
usually: 2000~5000
● Shared state ← Source of bugs
● Passive: Have to call object.method() to make the
object alive.
Actor:
● Light weight: Can create millions of actors;
usually: ~2.5 million actors/GB
● Shared nothing
● Active: Actors are alive by themselves. ← Easy to
model programs that have millions of on-going things
(very high level of concurrency), like MMOG games.
5. Concurrency: Actor vs Thread
● Thread: n dimensions, hard to reason about.
● Actor: 1D, one thing at a time.
var1
var2
6. Concurrency: Actor vs Thread
● Actor is a high level logical way to think, to
model programs.
● At lower level, actors run above a thread
pool.
9. Demo: Counter
// First, define messages
object Counter {
case class Inc(amount: Int)
case class Dec(amount: Int)
}
10. import akka.actor.Actor
// Define actor state and msg handler
class Counter(name: String) extends Actor {
// Actor state
private var value = 0
override def preStart() {
println(s"I'm alive: $name")
}
override def postStop() {
println(s"I'm dead: $name")
}
...
11. ...
import Counter._
// Msg handler
def receive = {
case Inc(amount) =>
value += amount
println(s"Value: $value")
case Dec(amount) =>
value -= amount
println(s"Value: $value")
}
}
12. import akka.actor.{ActorSystem, Props}
// Think of this as a thread pool
val system = ActorSystem("mysystem")
// Create actor reference (instance)
val c1 = system.actorOf(
Props(new Counter("mylock"))
)
// Send messages to the actor
c1 ! Counter.Inc(1)
c1 ! Counter.Dec(2)
14. Some actor antipatterns
Send mutable msgs between actors.
← May lead to bug, if actor A sends msg M to actor B, state
of B incorporates M, then M is later changed by A.
Fix: Use immutable msgs.
15. Some actor antipatterns
From inside actor:outsideObject.foo(new
Callback {
def onCallback() {
directlyModifyActorState()
}
}) ← May lead to bug, because the actor’s thread and the
callback’s thread may be 2 different threads. Remember:
An actor is like a single threaded process, can’t do more
than one thing at a time.
Fix: self ! msgFromCallback