English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Los programas cooperativos (coroutines) de Lua son muy similares a los hilos: tienen su propia pila, variables locales independientes, puntero de instrucciones independiente, y al mismo tiempo comparten variables globales y la mayoría de las otras cosas con otras cooperaciones.
La cooperación es una función muy poderosa, pero también muy compleja de usar.
La principal diferencia entre el hilo y la coroutine es que un programa con múltiples hilos puede ejecutar varios hilos al mismo tiempo, mientras que las coroutines necesitan ejecutarse en colaboración.
En cualquier momento especifico, solo una coroutine se está ejecutando, y la coroutine que se está ejecutando solo se suspenderá cuando se le pida explícitamente
Las coroutines son algo similar a múltiples hilos sincronizados, varios hilos esperando el mismo mutex tienen un poco de similitud con las coroutines.
Método | Descripción |
---|---|
coroutine.crear() | Crea una coroutine, devuelve la coroutine, el parámetro es una función, cuando se usa con reanudar, despierta la llamada a la función |
coroutine.reanudar() | Reiniciar la coroutine, se usa con create |
coroutine.rendir(co | Suspender la coroutine, establecer la coroutine en estado suspendido, esto se puede usar con resume para obtener muchos efectos útiles |
coroutine.estado() | Ver el estado de la coroutine Nota: el estado de la coroutine tiene tres: muerto, suspendido, corriendo, específicamente cuándo tiene tal estado, consulte el siguiente programa |
coroutine.envolver() | Crea una coroutine, devuelve una función, una vez que llamas a esta función, entras en la coroutine, tiene la misma función que create |
coroutine.corriendo() | Devuelve la coroutine corriendo, una coroutine es una hilo, cuando se usa corriendo, se devuelve el número de hilo de la coroutine |
-- archivo coroutine_test.lua co = coroutine.crear( función(i) print(i); end ) coroutine.reanudar(co, 1) -- 1 print(coroutine.estado(co)) -- muerto print("----------") co = coroutine.envolver( función(i) print(i); end ) co(1) print("----------") co2 = coroutine.crear( función() para i=1,10 hacer print(i) si i == 3 luego print(coroutine.estado(co2)) --corriendo print(coroutine.corriendo()) --hilo:XXXXXX end coroutine.rendir(co end end ) coroutine.reanudar(co2) --1 coroutine.reanudar(co2) --2 coroutine.reanudar(co2) --3 print(coroutine.estado(co2)) -- suspendido print(coroutine.corriendo()) print("----------")
El resultado de ejecutar el ejemplo anterior es:
1 muerto ---------- 1 ---------- 1 2 3 corriendo thread: 0x7fb801c05868 falso suspendido thread: 0x7fb801c04c88 true ----------
Se puede ver con coroutine.running, la implementación subyacente de coroutine es un hilo.
Cuando se crea una colaboración, se registra un evento en un nuevo hilo.
Cuando se utiliza resume para desencadenar eventos, se ejecuta la función coroutine de create, cuando se encuentra yield representa que se suspende la línea de hilo actual, esperando que se desencadene el evento de resume nuevamente.
A continuación, analizamos un ejemplo más detallado:
function foo (a) print("Salida de la función foo", a) return coroutine.yield(2 * a) -- devolver 2*El valor de a end co = coroutine.create(function (a , b) print("La salida de ejecución de la colaboración por primera vez", a, b) -- co-cuerpo 1 10 local r = foo(a + 1) print("La salida de ejecución de la colaboración por segunda vez", r) local r, s = coroutine.yield(a + b, a - b) -- Los valores de a, b son los ingresados por primera vez al llamar a la colaboración print("La salida de ejecución de la colaboración por tercera vez", r, s) return b, "Finalizar la colaboración" -- El valor de b es el传入第二次调用协作程序时的 end) print("main", coroutine.resume(co, 1, 10)) -- true, 4 print("--Línea de división----") print("main", coroutine.resume(co, "r")) -- true 11 -9 print("---Línea de división---") print("main", coroutine.resume(co, "x", "y")) -- true 10 end print("---Línea de división---") print("main", coroutine.resume(co, "x", "y")) -- no se puede recuperar la colaboración muerta print("---Línea de división---")
El resultado de ejecutar el ejemplo anterior es:
La salida de ejecución de la colaboración por primera vez 1 10 Salida de la función foo 2 main true 4 --Línea de división---- La salida de ejecución de la colaboración por segunda vez r main true 11 -9 ---Línea de división--- La salida de ejecución de la colaboración por tercera vez x y main true 10 Finalizar la colaboración ---Línea de división--- main false no se puede recuperar la colaboración muerta ---Línea de división---
El siguiente ejemplo es el siguiente:
Llamar a resume, despertar la colaboración, si la operación de resume tiene éxito devuelve true, de lo contrario devuelve false;
Ejecutar la colaboración;
Ejecutar hasta la sentencia yield;
Suspender de la colaboración, el primer resume devuelve;(Nota: aquí el yield devuelve, el parámetro es el de resume)
Segundo resume, despierta nuevamente la coroutine; (nota: los parámetros restantes en los parámetros de resume, además del primer parámetro, se usarán como parámetros de yield)
Se devuelve yield;
La coroutine continúa ejecutándose;
Si se llama al método resume en la coroutine después de que se complete su ejecución, se muestra: cannot resume dead coroutine
La fuerza de la combinación de resume y yield radica en que resume está en el contexto principal, introduce el estado externo (datos) al interior de la coroutine; mientras que yield devuelve el estado interno (datos) al contexto principal.
Ahora voy a usar las coroutines de Lua para resolver el problema del productor-Este es el problema clásico del consumidor
local newProductor function productor() local i = 0 while true do i = i + 1 send(i) -- Enviar el artículo producido al consumidor end end function consumer() while true do local i = receive() -- Obtener el artículo del productor print(i) end end function receive() local status, value = coroutine.resume(newProductor) return value end function send(x) coroutine.yield(x) -- x representa el valor que necesita enviarse, después de que se devuelva el valor, la coroutine se suspenderá end -- Iniciar programa newProductor = coroutine.create(productor) consumer()
El resultado de ejecutar el ejemplo anterior es:
1 2 3 4 5 6 7 8 9 10 11 12 13 ……