3

Von neumann architecture allows sequential processing of instructions. So, a single core within a CPU executes instructions sequentially.

Consider, OS providing 1-1 threading model(here) in a multi-core processor system,

Properties of concurrent system

  • Multiple actors(say, each thread assigned to a different core)
  • Shared resource(heaps, global variables, devices)
  • Rules for access(Atomic/Conditional synchronization)

With atomic synchronization mechanism(Lock) or conditional synchronization mechanism(say Semaphore), messages are indirectly passed between actors, that help compliance with rules for accessing shared resource.

In this answer, it says, The actor model helps to force you to program concurrent portions of your code as self contained nuggets that can be performed in parallel and without depending on another piece of code.

Question:

To help understand the difference between concurrent vs actor model,

Using actor model, How can one program concurrent portion(critical section) of code as self contained nuggets?

overexchange
  • 2,245
  • 2
  • 17
  • 47

2 Answers2

4

It's probably best to think of the actor model as the ancestor of object oriented programming; and compare it to OOP. However, because (I hope) you're already familiar with OOP I'm going to do the reverse.

For OOP, imagine you have a simple object with code vaguely like this:

integer currentValue = 0;

void incrementMethod(void) {
    currentValue = currentValue + 1;
}

void decrementMethod(void) {
    currentValue = currentValue - 1;
}

integer getValueMethod(void) {
    return currentValue;
}

void setValueMethod(integer value) {
    currentValue = value;
}

This has problems with concurrency, because multiple threads/CPUs could execute the methods at the same time and mess each other up. The "actor model" solution is to prevent direct access to the methods and provide isolation between "things" (objects/actors). The consequence is that you need some form of communication between the isolated things. That communication is message passing.

The silly example above could become:

integer currentValue = 0;

void main(void) {
    while(running) {
        message = getMessage();
        switch(messsage->type) {
            case INCREMENT_REQUEST:
                incrementMethod();
                break;
            case DECREMENT_REQUEST:
                decrementMethod();
                break;
            case GET_VALUE_REQUEST:
                getValueMethod(message->senderID);
                break;
            case SET_VALUE_REQUEST:
                setValueMethod();
                break;
            default:
                sendMessage(senderID, UNKNOWN_REQUEST, NULL);
        }
    }
}

void incrementMethod(void) {
    currentValue = currentValue + 1;
}

void decrementMethod(void) {
    currentValue = currentValue - 1;
}

void getValueMethod(messagePort senderID) {
    sendMessage(senderID, GETVALUE_REPLY, currentValue);
}

void setValueMethod(integer value) {
    currentValue = value;
}

Because the messaging serialises requests and because no data is shared between threads, no other form of concurrency control is necessary. Because no data is shared between threads, it's also highly distributable (e.g. you can have a system where different actors are on different physical computers). Because of the isolation between actors it's "more possible" (at least in theory) to support things like live update (e.g. by replacing an actor's code while the rest of the system is running) and fault tolerance (e.g. triple redundancy with 3 actors on 3 different computers instead of one). Finally, because an actor is able to accept an unknown request it's more extensible (e.g. you could send an ADD_VALUE_REQUEST message to an actor that it doesn't understand, and then make the actor understand that message type afterwards).

The main problem with (the naive implementation of) the actor model is performance - with one thread per actor plus the overhead of message passing the performance (as compared to OOP) would be extremely bad. There are multiple ways of fixing that, but the most common ways are to use many actors per thread and to allow actors within the same thread to call each other's methods directly (and avoid message passing in that case). With this in mind, you could define the origins of OOP as "actor model with only one thread where all actors can call each other's methods directly" (realising that multi-threading got retrofitted back on top of OOP later).

The other thing I need to point out is that for my example I'm being intentionally "low level" to help you understand what is happening behind the scenes. For a language designed for the actor model, the message handling loop shown above (main() in its entirety) would be implicit and not explicit; to save the programmer from typing so much stuff, and also so that the compiler can do the optimisations I mentioned.

Brendan
  • 3,895
  • 21
  • 21
  • The principal goal of the Actor model is not performance, but rather *scalability.* – Robert Harvey Jan 18 '17 at 08:22
  • "It's probably best to think of the actor model as the ancestor of object oriented programming; and compare it to OOP." – It's the other way around, actually: Alan Kay demonstrated an early version of Smalltalk-72 to Carl Hewitt, who then was inspired by its Message-Driven Computational Model to create the Actor Model. Alan Kay, in turn, had been inspired by PLANNER's Goal-Driven Computational Model. PLANNER, of course, had been designed by Carl Hewitt. Also, PLANNER was the precursor to Prolog, which was both the main inspiration and the original implementation language for Erlang, the most … – Jörg W Mittag Jan 18 '17 at 10:06
  • … commercially successful example of the Actor Model. Interestingly, the designers of Erlang didn't actually know about the Actor Model, they only learned about it later, so this is actually an example of convergent evolution. Note also that Alan Kay was heavily inspired by what would later become the Internet; he envisioned each object as its own virtual machine with its own instruction set (methods), its own RAM (instance variables), and all of that is private, you can only communicate with it by sending it messages (just like computers on a network). – Jörg W Mittag Jan 18 '17 at 10:09
  • @JörgWMittag: If you read historical information (interviews, etc) you'll notice that Alan Kay's original definition of "OOP" is much much closer to the actor model than it is to the "modern OOP" that everyone is familiar with (from languages like C++ and Java, where the language's design is devoid of "messages"). – Brendan Jan 19 '17 at 00:35
  • What are the hardware(processor) implications on exploiting "actor model"? Because there is no race condition and Von Neumann(one instruction at a time) would be a under use for exploiting "actor model" design. – overexchange Jan 20 '17 at 21:53
  • @overexchange: When 2 or more threads are involved (even on ancient computers with only one CPU, if there's a pre-emptive scheduler); there is plenty of scope for race conditions regardless of whether it's Von Neumann or Harvard. – Brendan Jan 23 '17 at 02:30
  • Can I say, your example using `getMessage()` & `sendMessage()` above, is nothing but, CSP(Communicating sequential processes), which GO encourages for? How close are CSP & actor model? – overexchange Jul 17 '17 at 21:10
2

Eliminate the critical section

Divide the work into individual parts in such a way that they no longer require concurrent access to a shared memory pool. This is inevitable, since actors can and often do execute in their own process.

One way to do this is to rewrite the code so that it is functionally pure, rather than mutable, object-oriented code. Functional programming, by its very nature, demands referential transparency. Referentially-transparent functions can be easily parallelized, because there is no critical section.

If your actors must still share a state space, use a database with ACID capabilities. It will take care of the concurrency and locking issues for you.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • This is nothing more than functional programming paradigm? So,then, I did not get the term "actor model". What is Carl Hewitt talking new by coining the term "actor model"? – overexchange Jan 18 '17 at 02:04
  • You can use whatever paradigm you want for writing each actor. But if you think *functionally,* it will help you figure out how to split the work so that each piece can be assigned to an actor. – Robert Harvey Jan 18 '17 at 02:05