Channels und Nebenläufigkeit
Channels und Nebenläufigkeit
Abschnitt betitelt „Channels und Nebenläufigkeit“Go-Style-Channels für nebenläufige Programmierung innerhalb von Prozessen.
Channels erstellen
Abschnitt betitelt „Channels erstellen“Channels sind Kommunikationsröhren für Coroutines. Erstellen Sie mit channel.new(capacity):
local ch = channel.new(1) -- Gepufferter Channel, Kapazität 1Gepufferte Channels
Abschnitt betitelt „Gepufferte Channels“Gepufferte Channels erlauben Sends ohne Blockierung bis der Puffer voll ist:
local ch = channel.new(3) -- Puffer hält 3 Elemente
-- Ohne Blockierung sendench:send(1)ch:send(2)ch:send(3)
-- In FIFO-Reihenfolge empfangenlocal v1, ok1 = ch:receive() -- 1, truelocal v2, ok2 = ch:receive() -- 2, truelocal v3, ok3 = ch:receive() -- 3, trueUngepufferte Channels
Abschnitt betitelt „Ungepufferte Channels“Ungepufferte Channels (Kapazität 0) synchronisieren Sender und Empfänger:
local ch = channel.new(0) -- Ungepuffertlocal done = channel.new(1)
coroutine.spawn(function() ch:send("from spawn") -- Blockiert bis Empfänger bereit done:send(true)end)
local val = ch:receive() -- Empfängt "from spawn"local completed = done:receive()Channel-Select
Abschnitt betitelt „Channel-Select“channel.select wartet auf mehrere Channels, gibt die erste bereite Operation zurück:
local ch1 = channel.new(1)local ch2 = channel.new(1)
ch1:send("ch1_value")
local result = channel.select{ ch1:case_receive(), ch2:case_receive()}
-- result ist eine Tabelle mit: channel, value, okresult.channel == ch1 -- trueresult.value -- "ch1_value"result.ok -- trueSelect mit Send
Abschnitt betitelt „Select mit Send“Verwenden Sie case_send um nicht-blockierende Sends zu versuchen:
local ch = channel.new(1)
local result = channel.select{ ch:case_send("sent")}
result.ok -- true (Send erfolgreich)
local v = ch:receive() -- "sent"Producer-Consumer-Muster
Abschnitt betitelt „Producer-Consumer-Muster“Ein Producer, ein Consumer:
local ch = channel.new(5)local done = channel.new(1)local consumed = 0
-- Consumercoroutine.spawn(function() while true do local v, ok = ch:receive() if not ok then break end consumed = consumed + 1 end done:send(consumed)end)
-- Producerfor i = 1, 10 do ch:send(i)endch:close()
local total = done:receive() -- 10Ping-Pong-Muster
Abschnitt betitelt „Ping-Pong-Muster“Zwei Coroutines synchronisieren:
local ping = channel.new(0)local pong = channel.new(0)local rounds_done = channel.new(1)
coroutine.spawn(function() for i = 1, 5 do ping:receive() pong:send("pong") end rounds_done:send(true)end)
for i = 1, 5 do ping:send("ping") pong:receive()end
local completed = rounds_done:receive()Fan-Out-Muster
Abschnitt betitelt „Fan-Out-Muster“Ein Producer, mehrere Consumer:
local work = channel.new(10)local results = channel.new(10)
-- 3 Worker startenfor w = 1, 3 do coroutine.spawn(function() while true do local job, ok = work:receive() if not ok then break end results:send(job * 2) end end)end
-- Arbeit sendenfor i = 1, 6 do work:send(i)endwork:close()
-- Ergebnisse sammelnlocal sum = 0for i = 1, 6 do local r = results:receive() sum = sum + rend-- sum = (1+2+3+4+5+6)*2 = 42Fan-In-Muster
Abschnitt betitelt „Fan-In-Muster“Mehrere Producer, ein Consumer:
local output = channel.new(10)local producer_count = 4local items_per_producer = 5
-- Producer startenfor p = 1, producer_count do coroutine.spawn(function() for i = 1, items_per_producer do output:send({producer = p, item = i}) end end)end
-- Alle Nachrichten sammelnlocal received = {}for i = 1, producer_count * items_per_producer do local msg = output:receive() table.insert(received, msg)end
-- Verifizieren dass alle Producer ihre Items gesendet habenlocal counts = {}for _, msg in ipairs(received) do counts[msg.producer] = (counts[msg.producer] or 0) + 1endChannels schließen
Abschnitt betitelt „Channels schließen“Schließen Sie Channels um Abschluss zu signalisieren. Empfänger erhalten ok = false wenn Channel geschlossen und leer ist:
local ch = channel.new(5)local done = channel.new(1)
coroutine.spawn(function() local count = 0 while true do local v, ok = ch:receive() if not ok then break end -- Channel geschlossen count = count + 1 end done:send(count)end)
for i = 1, 10 do ch:send(i)endch:close() -- Signalisiert keine weiteren Werte
local total = done:receive()Channel-Methoden
Abschnitt betitelt „Channel-Methoden“Verfügbare Operationen:
channel.new(capacity)- Channel mit Puffergröße erstellench:send(value)- Wert senden (blockiert wenn Puffer voll)ch:receive()- Wert empfangen, gibtvalue, okzurückch:close()- Channel schließench:case_send(value)- Send-Case für Select erstellench:case_receive()- Receive-Case für Select erstellenchannel.select{cases...}- Auf mehrere Operationen warten
Nächste Schritte
Abschnitt betitelt „Nächste Schritte“- Channel-Modul-Referenz - Vollständige API-Dokumentation
- Prozesse - Inter-Prozess-Kommunikation