Section 30.5 Chapter 30 · Actors and Concurrency 619
Communicate with actors only via messages
The key way the actors model addresses the difficulties of the shared data and
locks model is by providing a safe space—the actor’s act method—where
you can think sequentially. Put another way, actors allow you to write a
multi-threaded program as a bunch of independent single-threaded programs
that communicate with each other via asynchronous messaging. This sim-
plification works, however, only so long as messages are the only way you
let your actors communicate.
3
For example, a GoodActor could include a reference to itself in a mes-
sage to a BadActor, to identify itself as the source of that message. If
BadActor invokes some arbitrary method on GoodActor instead of sending
it a message with ‘!’, however, problems may ensue. The invoked method
might read private instance data in GoodActor, which may have been writ-
ten by a different thread. As a result, you would need to ensure that both the
BadActor thread’s reading of the instance data and the GoodActor thread’s
writing of it are synchronized on the same lock. The GoodActor’s private in-
stance data has become shared data that must be guarded by a lock. As soon
as you go around the message passing scheme between actors, therefore, you
drop back down into the shared data and locks model, with all the difficulties
you were trying to avoid in the first place by using the actors model.
On the other hand, this does not mean that you should never go around
message passing. Although shared data and locks is very difficult to get right,
it is not impossible. One difference between Scala’s approach to actors and
that of Erlang, in fact, is that Scala gives you the option to combine the actors
and shared data and locks models in the same program.
As an example, imagine you wanted multiple actors to share a common
mutable map. Since the map is mutable, the pure actors approach would be
to create an actor that “owns” the mutable map and define a set of messages
that allows other actors to access it. You could define a message for putting
a key-value pair into the shared map, getting a value given a key, and so
on, for all the operations you need to do on the map. In addition, you’d
need to define messages for sending asynchronous responses to actors that
made queries of the map. Another option, however, is to pass a thread-safe
map, such as ConcurrentHashMap from the Java Concurrency Utilities, in a
message to multiple actors, and let those actors use that map directly.
3
Another benefit is that a message send ensures the message object is safely published to
other threads, as described in Goetz, et. al., Java Concurrency in Practice, p. 49. [Goe06]
Cover · Overview · Contents · Discuss · Suggest · Glossary · Index