English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Lua Collaborative Programme (coroutine) sind ähnlich wie Threads: Sie haben eigenen Stack, eigene lokale Variablen, eigenen Befehlszeiger und teilen gleichzeitig globale Variablen und andere Dinge mit anderen Collaborationsprogrammen.
Collaboration ist eine sehr starke Funktion, aber sie ist auch sehr komplex zu verwenden.
Der Hauptunterschied zwischen Threads und Kollaborationen liegt darin, dass ein Programm mit mehreren Threads mehrere Threads gleichzeitig ausführen kann, während Kollaborationen zusammenarbeiten müssen, um zu arbeiten.
Zu jedem beliebigen Zeitpunkt läuft nur ein Kollaboration, und die laufende Kollaboration wird nur dann gehängt, wenn sie ausdrücklich angefordert wird
Kollaborationen sind etwas ähnlich wie synchrone Mehrkerntreads, einige Threads, die auf denselben Thread-Schutzschlüssel warten, sind etwas ähnlich Kollaborationen.
Methode | Beschreibung |
---|---|
coroutine.create() | Erstellt ein coroutine, gibt ein coroutine zurück, das Argument ist eine Funktion, wenn es zusammen mit resume verwendet wird, wird die Funktion aufgeweckt |
coroutine.resume() | coroutine neu starten, zusammen mit create verwenden |
coroutine.yield() | coroutine hängen lassen, den Zustand des coroutines auf suspended setzen, was zusammen mit resume viele nützliche Effekte haben kann |
coroutine.status() | Status eines coroutines anzeigen Anmerkung: Der Zustand eines coroutines kann dreierlei sein: tot, suspended, laufend, wann genau solche Zustände auftreten, siehe das folgende Programm |
coroutine.wrap() | Erstellt ein coroutine, gibt eine Funktion zurück, sobald diese Funktion aufgerufen wird, tritt das coroutine ein, was der Funktion create ähnelt |
coroutine.running() | Gibt den laufenden coroutine zurück, ein coroutine ist ein Thread, wenn "laufend" verwendet wird, wird die Thread-Nummer eines coroutines zurückgegeben |
-- coroutine_test.lua Datei co = coroutine.create( function(i) print(i); end ) coroutine.resume(co, 1) -- 1 print(coroutine.status(co)) -- tot print("----------") co = coroutine.wrap( function(i) print(i); end ) co(1) print("----------") co2 = coroutine.create( function() for i=1,10 tun print(i) if i == 3 dann print(coroutine.status(co2)) --laufend print(coroutine.laufend()) --thread:XXXXXX end coroutine.yield() end end ) coroutine.resume(co2) --1 coroutine.resume(co2) --2 coroutine.resume(co2) --3 print(coroutine.status(co2)) -- suspended print(coroutine.laufend()) print("----------")
Die Ausgabe des obigen Beispiels beträgt:
1 tot ---------- 1 ---------- 1 2 3 laufend thread: 0x7fb801c05868 false suspended thread: 0x7fb801c04c88 true ----------
coroutine.running zeigt, dass coroutine im Untergrund eine Thread ist.
Wenn ein Koroutinen erstellt wird, wird ein Ereignis in einem neuen Thread registriert.
Wenn der Aufruf von resume ein Ereignis auslöst, wird die coroutine-Funktion von create ausgeführt. Wenn yield erreicht wird, bedeutet das, dass der aktuelle Thread pausiert wird und auf den erneuten Aufruf von resume durch ein Ereignis gewartet wird.
Nun analysieren wir ein detaillierteres Beispiel:
function foo (a) print("foo Funktionsausgabe", a) return coroutine.yield(2 * a) -- zurückgeben 2*Der Wert von a end co = coroutine.create(function (a , b) print("Erste Koroutinen-Ausführungsausgabe", a, b) -- co-body 1 10 local r = foo(a + 1) print("Zweiter Koroutinen-Ausführungsausgabe", r) local r, s = coroutine.yield(a + b, a - b) -- Die Werte von a, b sind die, die beim ersten Aufruf des Koroutinen übergeben werden print("Dritter Koroutinen-Ausführungsausgabe", r, s) return b, "Koroutinen beenden" -- Der Wert von b ist der, der beim zweiten Aufruf des Koroutinen übergeben wird end) print("main", coroutine.resume(co, 1, 10)) -- true, 4 print("--Trennlinie----") print("main", coroutine.resume(co, "r")) -- true 11 -9 print("---Trennlinie---") print("main", coroutine.resume(co, "x", "y")) -- true 10 end print("---Trennlinie---") print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine print("---Trennlinie---")
Die Ausgabe des obigen Beispiels beträgt:
Erste Koroutinen-Ausführungsausgabe 1 10 foo-Funktionsausgabe 2 main true 4 --Trennlinie---- Zweiter Koroutinen-Ausführungsausgabe r main true 11 -9 ---Trennlinie--- Dritter Koroutinen-Ausführungsausgabe x y main true 10 Koroutinen beenden ---Trennlinie--- main false cannot resume dead coroutine ---Trennlinie---
Der obige Beispiel fortgesetzt wie folgt:
Aufruf von resume, um den Koroutinen zu wecken, resume gibt erfolgreich zurück, wenn der Vorgang erfolgreich ist, sonst gibt er false zurück;
Koroutinen werden ausgeführt;
Bis zum yield-Ausdruck ausführen;
Der Yield-Syntask pausiert den Koroutinen, der erste Aufruf von resume gibt zurück;(Hinweis: Hier gibt yield zurück, der Parameter ist der von resume übergebene Parameter)
Zweite resume, das Synchronisationsprogramm wird erneut geweckt;(Beachten Sie: Die zusätzlichen Parameter im resume-Parameter sind die Parameter für yield)
yield zurückgeben;
Synchronisationsprogramm fortsetzen;
Wenn der Synchronisationsprogramm nach dem Fortsetzen der Ausführung weiterhin den resume-Methodenaufruf ausführt, wird ausgegeben: cannot resume dead coroutine
Die starke Seite der Kombination von resume und yield liegt darin, dass resume im Hauptprogramm steht und den externen Zustand (Daten) in das Synchronisationsprogramm einbringt; während yield den internen Zustand (Daten) in das Hauptprogramm zurückbringt.
Ich werde jetzt die Synchronisationsprogramme von Lua verwenden, um das Produzentenproblem zu lösen-Das klassische Verbraucherproblem.
local newProductor function productor() local i = 0 while true do i = i + 1 send(i) -- Senden Sie das hergestellte Item an den Verbraucher end end function consumer() while true do local i = receive() -- Erhalte das Item vom Produzenten print(i) end end function receive() local status, value = coroutine.resume(newProductor) return value end function send(x) coroutine.yield(x) -- x bedeutet den zu sendenden Wert, nach dem Wert wird der Synchronisationsprogramm angehalten end -- Programm starten newProductor = coroutine.create(productor) consumer()
Die Ausgabe des obigen Beispiels beträgt:
1 2 3 4 5 6 7 8 9 10 11 12 13 ……