Die Lösung für nebenläufiges Denken: Promises

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4254
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Die Lösung für nebenläufiges Denken: Promises

Beitrag von Chromanoid »

Gerade auf Reddit gesehen: https://github.com/vasanthk/async-javascript/ "Evolution of Asynchronous JavaScript" passt zum Thema :)
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Die Lösung für nebenläufiges Denken: Promises

Beitrag von Alexander Kornrumpf »

Chromanoid hat geschrieben:Ich glaube hier ist wieder unser unterschiedliches Verständnis von Nebenläufigkeit das Problem. So wie ich das gelernt habe, gilt nur weil etwas sequentiell ausgeführt wird noch nicht, dass es nicht zwei Prozesse sind, die nebenläufig zu einander ausgeführt werden (siehe https://books.google.de/books?id=9dKYNO ... &q&f=false). Da die Generatoren in node.js ja scheinbar auch auf externe Ressourcen warten können und dann andere Callbacks ausgeführt werden, ist die Reihenfolge der Operationen nicht mehr total sondern nur noch partiell geordnet und dann spricht man meines Wissens nach von Nebenläufigkeit. Callbacks oder auch Interrupts sind deswegen meiner Interpretation nach auch eine Form der Nebenläufigkeit, es gibt nämlich keine totale Ordnung der Anweisungen, siehe https://www.informatik.uni-hamburg.de/T ... script.pdf S. 3 bzw. https://www4.cs.fau.de/Lehre/SS08/V_SPI ... /H2-A6.pdf S. 1. Aber das ist wirklich ein ziemliches Herumgereite auf den Definitionen und ich lasse mich gerne eines Besseren belehren.

[...]

Genauso auch die Programmteile, die mit yield auf etwas warten.
Geschenkt. Ich schreib nochmal worauf ich hinaus will:

Yield hält den Generator an und übergibt einen Wert an den Aufrufer. Der Aufrufer kann einen Wert zurück an das yield geben und damit den Generator an dieser Stelle fortsetzen. Die Reihenfolge in der das passiert ist vollkommen deterministisch. Yield definiert also einen Punkt an dem der Generator angehalten und gestartet werden kann. Wenn du so willst ein Funktionskopf und return an derselben Stelle. Zu sagen yield würde auf etwas "warten" ist so wie zu sagen, eine Funktion würde darauf warten aufgerufen zu werden. Yield führt nicht mehr Nebenläufigkeit ein, als ein Funktionsaufruf, denn: Ein Generator ist keine Koroutine!

Was hier passiert ist, dass schlaue Menschen erkannt haben, dass man Koroutinen "elegant" mit Generator-Syntax implementieren kann. Was die Beispiele des Threaderstellers nicht zeigen, wohl aber dein Link zu Generatoren, ist dass nicht das yield auf ein asynchrones Ereignis wartet, sondern das andere Ende was dann, wenn das Ereignis eintritt, den Generator fortsetzt. Deswegen "invertiert" bzw. "von hinten aufgezäumt". Im Ergebnis sieht es so aus, als würde yield darauf warten. Die Magie liegt aber nicht im yield sondern in Coroutine. Alle Nebenläufigkeit (nach deiner Def.) wird durch Coroutine (eine Funktion des Promise-API) eingeführt, nicht durch den Generator. Es ist ein Pattern, das Generatoren verwendet, kein Sprachkonstrukt.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4254
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Die Lösung für nebenläufiges Denken: Promises

Beitrag von Chromanoid »

Ah, ich verstehe jetzt was Du meinst. Während das Sprachkonstrukt des Generators die Möglichkeit bereitstellt den Programmfluss einer Routine (die Generator-Routine) zu unterbrechen und später wieder aufzunehmen (eine wichtige Voraussetzung für Koroutinen), muss die Ausführung der verschiedenen Generator-Routinen noch in Bezug auf nebenläufige Ereignisse orchestriert werden, damit sie als nebenläufige Koroutinen funktionieren.
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Die Lösung für nebenläufiges Denken: Promises

Beitrag von Alexander Kornrumpf »

Chromanoid hat geschrieben:Ah, ich verstehe jetzt was Du meinst. Während das Sprachkonstrukt des Generators die Möglichkeit bereitstellt den Programmfluss einer Routine (die Generator-Routine) zu unterbrechen und später wieder aufzunehmen (eine wichtige Voraussetzung für Koroutinen), muss die Ausführung der verschiedenen Generator-Routinen noch in Bezug auf nebenläufige Ereignisse orchestriert werden, damit sie als nebenläufige Koroutinen funktionieren.
Ja. Um nochmal auf Callbacks vs. Generatoren zurückzukommen, Ich glaube, dass die "gotchas" bei der Sache aus der Orchestrierung kommen, die das sagst du richtig, trotz single-threadedness, nicht transparent funktioniert (und wahrscheinlich auch nicht transparent sein kann, ich wüsste nicht wie). Die Orchestrierung ist aber für die Callbacks im Prinzip die gleiche, mit den gleichen "gotchas".

Dass man unabhängig davon eine Syntax subjektiv zugänglicher finden kann als eine andere bleibt davon natürlich unberührt. Generatoren sind sicher etwas worüber man mal einen Nachmittag nachdenken kann bevor man sie naiv einsetzt. Insofern nochmal danke, dass du mich bei besagtem Nachdenken unterstützt hast.
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4254
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: Die Lösung für nebenläufiges Denken: Promises

Beitrag von Chromanoid »

Ebenso Danke! Ohne Deine Hinweise, hätte ich von der Umsetzung eine falsche Vorstellung behalten. Das Generator-Konstrukt war mir vor dem Thema hier auch noch unbekannt. In Python und wohl noch einigen anderen Sprachen gibt es ähnliche Implementierungen von Koroutinen damit. Echte parallele Verarbeitung ist mir da irgendwie lieber. Das Argument aus http://blog.stevenedouard.com/asynchron ... ncurrency/ für node.js, bei IO als Flaschenhals, hatte mich noch etwas irritiert:
C# runtime doesn’t scale as well to I/O-bound tasks like loading washing machines, primarily due to the overhead of context switching of threads, it does scale better at computationally intensive, CPU-bound tasks.
Dem scheint wirklich so zu sein, da .NET wohl einen Threadpool für IO-Aufgaben hat (siehe http://stackoverflow.com/questions/8905 ... e-js-possi). Ich glaube Java ist an der Stelle rudimentärer und sollte dieses Problem nicht haben.
KayZ
Beiträge: 47
Registriert: 05.01.2015, 23:46
Echter Name: Dennis

Re: Die Lösung für nebenläufiges Denken: Promises

Beitrag von KayZ »

@antisteo: Ich muss einfach mal Dart in den Raum werfen. Bei Dart ist das ganze async-Zeug direkt Teil der Programmiersprache und aller APIs ohne dass es unterschiedliche Implementationen durch verschiedene Libraries gibt. Und sie decken wirklich alles ab, also nicht nur Futures sondern auch Streams (asynchrone Listen) und es gibt auch await, so dass man dort nicht mal die beispielhaft genannte 100 fache Verkettung von Futures/Promises machen muss, sondern man kann es nahezu wie synchronen Code schreiben.

Also zum Beispiel statt:

Code: Alles auswählen

HttpServer.bind('127.0.0.1', 4444)
  .then((server) => print('${server.isBroadcast}'))
  .catchError(print);
kann man auch:

Code: Alles auswählen

try {
  var server = await HttpServer.bind('127.0.0.1', 4444);
  print('${server.isBroadcast}');
} catch (e) {
  print(e);
}
schreiben.

https://www.dartlang.org/docs/tutorials/futures/
https://www.dartlang.org/docs/tutorials/streams/

Im zweiten Link sieht man das ganze anhand eines asynchronen Generators dessen Werte innerhalb einer await for Schleife abgerufen werden und dessen Ergebnis eine Future ist. Der Code liest sich, abgesehen von ein paar keywords, wie synchroner Code.

Warum ich Dart in den Raum werfe? Man kann Dart für clientseitige als auch für serverseitige Anwendungen nutzen. Im Browser kompiliert man es nach Javascript (im Normalfall performanter als handgeschriebenes JS und durch Treeshaking (nur wirklich verwendeter Code wird in JS umgewandelt) teilweise auch kleiner als eine JS-Anwendung mit x-Libs die man so benötigt um halbwegs vernünftiges JS schreiben zu können) und auf dem Server läuft es nativ. Wie in Javascript gibt es in Dart nur einen Thread, man kann aber mehrere "Isolates" erzeugen die allerdings nur über Nachrichten miteinander kommunizieren können (es gibt keinen globalen Speicherbereich in dem mehrere Isolates rumhantieren und sich gegenseitig in die Quere kommen können, also keine concurrent modification exceptions möglich, wie man sie z.B. aus Java kennt).
Alexander Kornrumpf
Moderator
Beiträge: 2106
Registriert: 25.02.2009, 13:37

Re: Die Lösung für nebenläufiges Denken: Promises

Beitrag von Alexander Kornrumpf »

Hier macht es jemand live mit python vor:

http://pyvideo.org/video/3432/python-co ... nd-up-live
Antworten