Wie man mehrere 'Threads' implementiert, die nur in einem Thread laufen

8

In letzter Zeit habe ich gedacht: Wie implementieren sie mehrere "Threads" in nur einem Thread?

Ich meine, wie sie mehrere parallel laufende Code-Teile in nur einem Thread implementieren? Wie speichern sie den Zustand des "Threads", erstellen einen Interrupt und übergeben die CPU an die nächste?

Ich denke, dass die Scala-Akteure dies umsetzen. Aber wie?

Dies kann für JVM oder C beantwortet werden, es spielt keine Rolle. Ich möchte nur wirklich die Theorie davon lernen.

    
José Leal 23.03.2011, 09:50
quelle

6 Antworten

6

Ich denke, Sie verwirren Koroutinen und grüne Fäden hier.

Coroutinen geben die Kontrolle, wenn sie dazu bereit sind, ohne Unterbrechung auf, daher ist die Frage nach der Unterbrechung irrelevant. Scala-Akteure werden als Koroutinen implementiert.

Grüne Threads sind Benutzermodus-Threads, die von einer virtuellen Maschine ohne Verwendung systemeigener Betriebssystemfunktionen implementiert werden. Offensichtlich kann die virtuelle Maschine beliebige Anweisungen in den ausgeführten Code einfügen, um zu prüfen, ob sie zu einem anderen Thread wechseln müssen.

    
axtavt 23.03.2011 10:19
quelle
4

Mit Schauspielern ist es einfach, anstatt einen Thread pro Akteur zu verwenden, verwenden Sie denselben Thread zum Ausführen von Nachrichten für mehrere Akteure. Wenn jedoch ein Akteur einen blockierenden Anruf oder eine schwere Berechnung durchführt, muss ein anderer Thread verwendet werden, um Nachrichten in anderen Akteuren auszuführen.

Grüne Threads sind leichte Threads, die auf VM-Ebene implementiert werden können. Grüne Threads werden immer einem oder mehreren Betriebssystem-Threads zugeordnet. Die Synchronisierung und das Thread-Switching werden von der VM im Benutzerbereich ausgeführt, wodurch der Overhead erheblich reduziert werden kann. Grüne Threads haben jedoch Nachteile. So kann der Thread durch IO-Aufrufe blockiert werden und die VM kann den OS-Thread nicht für einen anderen grünen Thread "wiederverwenden" und stattdessen einen zusätzlichen OS-Thread verwenden.

Eine andere Lösung ist die Verwendung von Fortsetzungen, wie sie im Scala-Compiler implementiert sind. Die Unterbrechung und Fortführung der Ausführung wird dann auf der JVM-Bytecode-Ebene gehandhabt, auf der der lokale Zustand gespeichert und wiederhergestellt wird. Es wird keine VM-Unterstützung benötigt.

    
Jesper Nordenberg 23.03.2011 10:30
quelle
3

Meinst du wie Aufgaben in einem ExecutorService oder ScheduledExecutorService in Java?

Diese Aufgaben werden zu einer Warteschlange hinzugefügt und bis zum Abschluss vervollständigt. Wenn einer fertig ist, beginnt ein anderer. Wenn Sie eine Schleife mit einer Verzögerung haben, können Sie stattdessen eine Wiederholung geplanter Aufgaben verwenden. Es wird für jede Iteration abgeschlossen und ermöglicht die Ausführung weiterer Aufgaben.

Wenn Sie mehr Details erfahren möchten, könnten Sie den Code interessant finden.

    
Peter Lawrey 23.03.2011 09:58
quelle
2

Verwenden Sie Koroutinen

    
E. Verda 23.03.2011 10:10
quelle
2

Die Akka-Bibliothek ist eine wirklich nette Umsetzung des Schauspielermodells. Es hat eine ziemlich gute gerade Java API (zusätzlich zu der Scala), und das Dokument ist hübsch gut .

    
MPG 23.03.2011 13:40
quelle
1

Eine Möglichkeit besteht darin, dass sich das Threading-Paket im Benutzercode selbst für eine Art von Timer-Interrupt vom Kernel registriert. Wenn ein solcher Interrupt empfangen wird, kann er dem Kernel mitteilen, dass er die Ausführung aller Kernel-Threads anhalten soll, die selbst mehrere unterschiedliche Threads ausführen. Für jeden dieser Threads kann der Timer-Interrupt-Code den Stapel auf diese Threads prüfen, wichtige Informationen (Register, Stapelzeiger, Programmzähler usw.) an einem Hilfsort aufzeichnen und dann die gespeicherte Information für einen anderen der simulierten laden Threads, die auf diesem tatsächlichen Thread ausgeführt werden. Es kann dann den Kernel-Thread fortsetzen, der den simulierten Thread ausführt. Auf diese Weise können Sie den Kontextwechsel zwischen den mehreren Threads simulieren, die auf einem einzelnen Kernel-Thread ausgeführt werden.

Um etwas wie Sperren zu implementieren, können Sie alle Sperrinformationen lokal in Ihrem Benutzerbereich verfolgen. Wenn ein simulierter Thread versucht, eine Sperre zu erhalten, können Sie überprüfen, ob der Thread die Sperre erfolgreich erhalten kann. Wenn ja, gibst du ihm einfach das Schloss. Andernfalls simulieren Sie einen Kontextwechsel, indem Sie den simulierten Thread austauschen, der auf diesem echten Thread ausgeführt wird, und markieren dann den simulierten Thread als blockiert, bis die Sperre wieder frei wird.

Das ist nur ein Anfang - es gibt eine Menge anderer Details hier (was ist, wenn einer der simulierten Threads versucht, eine blockierende E / A-Operation zu machen? Sie können den Kernel-Thread nicht einfach blockieren, da dies alle anhalten würde simulierte Threads!), aber das ist der Kern der Idee.

    
templatetypedef 23.03.2011 09:58
quelle

Tags und Links