Stimmt meine Beschreibung des Darstellermodells?

13

Wenn ich verstanden habe, ist das Darstellermodell genau wie das Objektmodell, aber mit ein paar Unterschieden:

  1. JEDES Objekt erzeugt einen eigenen separaten Thread und es ist kein Problem, auch wenn Sie Tausende von Objekten haben.
  2. Akteure interagieren nicht durch Aufrufen von Funktionen und Abrufen von Rückgabewerten, sondern durch Senden und Empfangen von Nachrichten.
  3. Wenn Sie nicht gegen dieses Modell verstoßen, nutzt Ihre App die Parallelität ohne das Risiko von Rennbedingungen.
  4. Alles, was Sie in OO tun können, können Sie mit Schauspielern tun, aber besser. Das Problem ist, dass alles, was wir in den letzten Jahren codiert haben, OO-basiert war - aber ein Übergang steht bevor.

Nehmen wir zum Beispiel an, ich muss eine 3D-Vektorklasse / einen 3D-Akteur definieren, zwei Instanzen erstellen und eine Summenoperation für sie aufrufen.

OBJEKTORIENTIERTEN:

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

SCHAUSPIELER-MODELL:

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
}

Ist es das? Oder liege ich völlig falsch?

WindScar
quelle
Leichte Akteure oder Mikroagenten oder Datenflusskomponenten verwenden nicht unbedingt ihren eigenen Thread. :-) Überprüfen Sie die folgenden Begriffe: akteursbasierte Programmierung, agentenbasierte Programmierung, datenflussbasierte Programmierung. Sie sind sich sehr ähnlich, haben aber unterschiedliche Einschränkungen. Ohh, ich werde dies als Frage stellen ;-)
Inf3rno

Antworten:

12

Die kurze Antwort ist nein, es ist nicht richtig.

  1. Startet einigermaßen korrekt (jeder Actor führt zumindest potentiell als eigenständiger Thread aus), geht dann aber größtenteils von den Schienen. Es gibt nichts an dem Modell , was dazu führt, dass viele Threads gut funktionieren - das hängt von der Implementierung ab. Die einfache Erstellung vieler Threads übt allenfalls Druck auf die Implementierung aus, um ein effizientes Threading bereitzustellen. Zumindest in Bezug auf das Modell ist jede Ähnlichkeit zwischen Schauspielern und Objekten meistens zufällig. "Objekt" hat ziemlich spezifische Auswirkungen auf die Art und Weise, wie Sie Code und Daten kombinieren. Ein Akteur wird im Allgemeinen sowohl Code als auch Daten einbeziehen, impliziert jedoch wenig darüber, wie sie kombiniert werden (abgesehen von der Tatsache, dass die einzigen Daten, die für die Außenwelt sichtbar sind, Nachrichten sind).

  2. Die übliche Art, die Interaktion zu beschreiben, ist das Senden von Nachrichten, ja. Ich habe kein Zitat zur Hand, aber jemand hat vor langer Zeit bewiesen, dass Mechanismen wie virtuelle C ++ - Funktionen für das Senden von Nachrichten isomorph sind (da virtuelle Funktionen normalerweise implementiert sind, verwenden Sie einen Versatz in einer vtable - aber wenn Sie Wird stattdessen ein Offset in eine Nachrichtentabelle gesendet, ist der Effekt derselbe.

  3. So einfach ist das nicht. Wenn Sie eine Kopie finden können, hat Henry Baker (mit jemand anderem, an dessen Namen ich mich noch nicht erinnere) eine Abhandlung über die Regeln geschrieben, die für die Datenkonsistenz im Actor-Modell erforderlich sind.

  4. "Besser" ist bestenfalls höchst subjektiv. Einige Probleme sind von Natur aus sehr parallel und umfassen tatsächlich eine große Anzahl von im Wesentlichen autonomen Entitäten mit minimaler Interaktion, die hauptsächlich asynchron ist. In diesem Fall kann das Schauspielermodell sehr gut funktionieren. Bei anderen Problemen ist das wirklich nicht der Fall. Einige Probleme sind fast ausschließlich serieller Natur. Andere können parallel ausgeführt werden, erfordern jedoch eine enge Synchronisation zwischen diesen Aktionen (z. B. im Wesentlichen ein SIMD-ähnlicher Modus, in dem Sie jeweils einen Befehl ausführen, aber jeder Befehl auf eine große Anzahl von Datenelementen angewendet wird). Es ist sicherlich möglich, beide Arten von Problemen mit dem Akteurmodell zu lösen. Bei solchen Problemen ist jedoch häufig ein erheblicher Mehraufwand erforderlich, für den nur ein geringer oder gar kein Gewinn erzielt wird.

Jerry Sarg
quelle
Es gibt keine Beziehung zwischen der Anzahl der Akteure und der Anzahl der Threads. Das Darstellermodell garantiert, dass eine bestimmte Instanz jeweils nur von einem Thread bearbeitet wird, sodass Ihre Darsteller bereits threadsicher sind und Sie keine Synchronisations- und Sperrstrategien in ihnen verwenden müssen.
Rob Crawford
@RobCrawford: Dies ist ein (ziemlich trivialer) Weg, um die Datenkonsistenz im Actor-Modell sicherzustellen. Das Hewitt / Baker-Papier deckt mehr Möglichkeiten ab, wie zum Beispiel mehrere Kopien eines Schauspielers, die in verschiedenen Threads laufen (hmm ... angesichts meiner Antwort frage ich mich, ob ich mich zu der Zeit ehrlich nicht an Carl Hewitts Namen erinnern konnte oder war ironisch sein, als ich es schrieb).
Jerry Coffin
Ist die Asynchronität der Nachrichtenübermittlung nicht ein wesentliches Element des Modells? Dies würde sicherlich verhindern, dass es bei virtuellen Funktionsaufrufen, die synchroner Natur sind, isomorph ist. Oder ist die Unterscheidung aus irgendeiner Perspektive irrelevant?
Boycy
2

Zu 1: Ich habe mit einer von einem Akteur modellierten (ish) Thread-Anwendung gearbeitet, daher ist es durchaus möglich, die große Thread-Nummer zu ignorieren, die dies nahelegt. AFAIK, Threads sind keineswegs leichte Objekte, daher ist es wahrscheinlich nicht wünschenswert, für jeden Schauspieler einen zu haben, je nachdem, wie viele Schauspieler Sie verwenden.

Zu 3: Ich bin mir ziemlich sicher, dass Rennbedingungen in akteursmodellierten Systemen einfach aufgrund der Programmierlogik auftreten können.

Zu 4: Besser definieren? Ich habe die Erfahrung gemacht, dass asynchrone Logik viel schwieriger zu lesen ist als synchrone. Beispiel: In Ihrem obigen Beispiel wissen Sie nicht, welche Operation für welches Ergebnis verantwortlich ist. Daher ist eine zusätzliche Nachrichtenverfolgung erforderlich. Sobald dies hinzugefügt wurde und andere eingehende und ausgehende Nachrichten in der Logik enthalten sind, wird die Absicht des Codes auf mehrere Sende- / Empfangsfunktionen verteilt.

Trotzdem bin ich ein großer Fan von Schauspieler-Modellen für die oberen Ebenen einer Anwendung. Dies kann die Entkopplung erleichtern, da das Hinzufügen von Abhängigkeiten etwas schwieriger ist als das Hinzufügen einer Funktion. Ich habe auch nicht viel Erfahrung mit höheren Niveaus als Java-Sprachen, und andere Paradigmen könnten Asynchronität auf grundlegendere Weise unterstützen.

Schlepper
quelle
Zu # 1: Nun, "Thread" kann sich auf viele Dinge beziehen. Betriebssystem-Threads sind normalerweise ziemlich schwer, aber es gibt Sprachlaufzeiten, die intern Hunderte, Tausende oder sogar Millionen von "Threads" für die Ausführung innerhalb einer kleinen Anzahl von Betriebssystem-Threads verarbeiten. In einigen Implementierungen werden solche Modelle anscheinend auf Dutzende von Kernen skaliert (ich habe Aussagen gesehen, dass aktuelle GHC-Versionen mit 32 Kernen gut funktionieren).