13

If I understood, the actor model is just like the object model, but with a few differences:

  1. EVERY object spawns it's own separate thread and its not a problem even when you have thousands of objects.
  2. Actors don't interact by calling functions and getting return values but instead by sending and receiving messages.
  3. If you don't violate that model your app will be using concurrency to its full power without any risks of race conditions.
  4. Everything you can do in OO you can do using actors but better, the problem being that everything we coded in the last years was OO based - but a transition is imminent.

So for instance, suppose I have to define 3d vector class/actor, create two instance and call a sum operation on them.

OBJECT ORIENTED:

class V3d {
   constructor V3d(x,y,z) //bla
   float x,y,z;
   function sum(V3d b) 
   { 
      return V3d(x+b.x,y+b.y,z+b.z); 
   }
}

//using:
mySum = V3d(1,2,3).sum(V3d(3,2,1)) //creates 2 instances, sum, returns instantly
drawPoint(mySum) //uses the result

ACTOR MODEL:

actor V3d 
{
    constructor V3d(x,y,z) //bla
    float x,y,z;
    loop 
    {
       receive 'sum',b:V3d :
           send(caller,'sumResult',V3d(x+b.x,y+b.y,z+b.z))
    }
 }

//using:
send(V3d(1,2,3),'sum',V3d(3,2,1)) //creates 2 instances, send to the first one a request to sum with the second one

loop 
{
   receive 'sumResult',result:
      drawPoint(result) //receives result and draws it
}

Is that it? Or am I completely wrong?

  • Lightweight actors or microagents or dataflow components do not necessarily use their own thread. :-) Check the following terms: actor-based programming, agent-based programming, dataflow-based programming. They are very similar, but they have different constraints. Ohh I'll ask this as a question ;-) – inf3rno Aug 19 '14 at 7:06
12

The short answer is no, it's not correct.

  1. starts reasonably correct (each Actor at least potentially executes as an independent thread), but then largely goes off the rails. There's nothing about the model that makes lots of threads work well -- that's up to the implementation. At most, the ease of creating lots of threads puts pressure on the implementation to provide efficient threading. At least as far as the model cares, any resemblance between actors and objects is mostly coincidental. "Object" carries fairly specific implications about how you combine code and data. An actor will generally involve both code and data, but implies little about how they're combined (other than the fact that the only data visible to the outside world is messages).

  2. The usual way of describing the interaction is as message sending, yes. I don't have a citation handy, but somebody proved quite a long time ago that mechanisms like C++ virtual functions are isomorphic to message sending (as virtual functions are normally implemented, you're using an offset into a vtable -- but if you sent an offset into a table of messages instead, the effect would be the same).

  3. It's not quite that simple. If you can find a copy, Henry Baker (with somebody else whose name I don't remember right now) wrote a paper about the rules necessary for data consistency in the Actor model.

  4. "Better" is highly subjective at best. Some problems are highly parallel in nature, and really do involve a large number of essentially autonomous entities, with minimal interaction that's primarily asynchronous. When that's the case, the actor model can work very well indeed. For other problems, that's really not the case. Some problems are almost entirely serial in nature. Others can be executed in parallel, but still require close synchronization between those actions (e.g., essentially a SIMD-like mode, where you execute one instruction at a time, but each instruction acts on on a large number of data items). It's certainly possible to solve both of these types of problems using the actor model -- but for such problems, it often involves a fair amount of extra work for little or no gain in return.

  • There's no relation between the number of actors and number of threads; what the actor model guarantees is that a given instance will only be operated on by a single thread at a time, so your actors are already thread-safe and you don't need to use synchronization and locking strategies inside them. – Rob Crawford Jan 3 '17 at 21:41
  • @RobCrawford: that's one (fairly trivial) way of ensuring data consistency in the Actor model. The Hewitt/Baker paper covers more possibilities, such as multiple copies of an Actor running in separate threads (hmm...looking at my answer, I'm wondering whether I honestly couldn't remember Carl Hewitt's name at the time, or was being ironic when I wrote it). – Jerry Coffin Jan 3 '17 at 23:01
  • Isn't asynchronicity of message passing an essential element of the model? That would surely prevent it from being isomorphic with virtual function calls, which are synchronous in nature. Or is the distinction irrelevant from some perspective? – boycy Jan 27 '17 at 19:55
2

Regarding 1: I have worked with single(ish) threaded Actor-modeled application, so it's quite possible to disregard the large thread number this suggests. AFAIK, threads are not lightweight objects by any means, so it's probably not desirable to have one for each actor, depending on how many actors you are using.

Regarding 3: I'm pretty sure race conditions can happen in actor modeled systems simply due to programming logic?

Regarding 4: Define 'better'? My experience has been that asynchronous logic can be much more difficult to read than synchronous stuff. e.g, in your example above, you don't know which operation is responsible for which result, so there is extra message tracking to do. Once that is added in and other messages in and out are included in the logic, the intent of the code is spread across several send/receive functions.

Having said all of that, I am a big fan of actor model use for the upper layers of an application. It can make decoupling easier, since adding dependencies is a bit harder than adding a function. I also don't have much experience with higher level than Java languages, and other paradigms might support asynchronous-ness in a more fundamental way.

  • Regarding #1: Well, "thread" can refer to many things. OS threads are usually fairly heavyweight, true, but there are language runtimes that internally handle hundreds, thousands, even millions of "threads" of execution within a small number of OS threads. In some implementations, such models apparently scale up to dozens of cores (I've seen statements that recent GHC versions play nice with 32 cores). – user7043 Oct 28 '11 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.