Pregunta

or put another way: are there proper uses of mutable messages?

The use case I am facing is that I want to process objects which basically are of type

Map<String,List<String>>

The typical processing an actor would do is to read or write some of the fields of the map. A condensed example is (leaving out null-tests etc.)

  map.get("somekey").add("new value");

My hunch is that keeping this immutable in Scala would be trivial by using the respective collection types. In Java it would require to go for some additional class library.

But: reading the Akka docs, I find that sending a message introduces a happens-before relation between the last access of the sender and the first access of the receiving actor. So if the map is not immutable, nevertheless the sender should see all data.

Suppose I can make sure that the sender will never touch the map again once it is send, is there any other problem to expect with regards to threaded data access to this map?

¿Fue útil?

Solución

The OP’s interpretation of the happens-before rule is correct: the “actor send rule” means that sending M to actor A happens-before processing M by A (this is what “the same” refers to).

To answer the main question: as long as only at most one actor can “own” the mutable map at any given point in time, this will work, and depending on the circumstances this may well be the most efficient solution to the problem. Guaranteeing the single-ownership will require a bit of discipline, though, which offsets the runtime advantage by a maintenance cost.

Although the original question leaves out the actual vehicle for transporting the Map I would like to reinforce Randall’s point that messages between actors should never be JDK types, since those lack semantic meaning. The Map should in this case be contained within a clearly named custom message type.

Otros consejos

You should be fine if the data is effectively immutable. This is easier to enforce if there data is immutable, however with discipline you can treat the map as effectively immutable after you send it.

In a nutshell, this is a rule to avoid a ton of really weird problems.

The underlying problem is that the Java VM has some weird rules when one thread modifies memory and another thread reads that memory. Google for "Memory barriers" if you want to know the gory details.

So this means every language running on the VM is affected.

These rules in turn make it hard to tell when it would be safe to read a message that someone sent since the writing thread might not have yet flushed it's CPU's cache.

The solution is to force people to use the immutable patterns since then, the VM will make sure that the caches are in fact flushed when the Akka core takes the message and passes it to another thread.

The Akka docs you reference state that the happens-before rules only apply to the same actor. So if you send a message from one sender actor to a different receiver actor, the happens-before rules don't apply.

Also, as your code base evolves over time, it's going to be increasingly difficult to "make sure" that the only actor who every modifies that Map is the original sender.

Why not create a new immutable Map in the original sender, or any other place you modify the message contents before sending it to another actor? Then you'll be 100% sure that no other actors can modify the message they've received, and you'll have easily avoided any concurrency problems.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top