Coroutine Lua
Qu'est-ce que la coroutine ?
La coroutine Lua est similaire à un thread : elle possède une pile indépendante, des variables locales indépendantes et un pointeur d'instruction indépendant, tout en partageant des variables globales et la plupart des autres choses avec d'autres coroutines.
La collaboration est une fonction très puissante, mais elle est aussi très compliquée à utiliser.
La différence entre les threads et les coroutines
La principale différence entre les threads et les coroutines est qu'un programme avec plusieurs threads peut exécuter plusieurs threads en même temps, tandis que les coroutines doivent s'exécuter en coopération avec chacun autre.
Une seule coroutine est en cours d'exécution à un moment donné, et la coroutine en cours d'exécution ne sera suspendue que lorsqu'on lui demandera explicitement de la suspendre.
Les coroutines sont quelque peu similaires aux multi-threads synchronisés, et plusieurs threads attendant le même thread lock sont quelque peu similaires à la collaboration.
Grammaire de base
方法 | 描述 |
---|---|
coroutine.create() | 创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用 |
coroutine.resume() | 重启coroutine,和create配合使用 |
coroutine.yield() | 挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果 |
coroutine.status() | 查看coroutine的状态 注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序 |
coroutine.wrap() | 创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复 |
coroutine.running() | 返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号 |
Les exemples suivants démontrent l'utilisation de chacune des méthodes ci-dessus :
-- coroutine_test.lua 文件 co = coroutine.create( function(i) print(i); end ) coroutine.resume(co, 1) -- 1 print(coroutine.status(co)) -- dead print("----------") co = coroutine.wrap( function(i) print(i); end ) co(1) print("----------") co2 = coroutine.create( function() for i=1,10 do print(i) if i == 3 then print(coroutine.status(co2)) --running print(coroutine.running()) --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.running()) print("----------")
Le résultat de l'exécution des exemples ci-dessus est :
1 dead ---------- 1 ---------- 1 2 3 running thread: 0x7fb801c05868 false suspended thread: 0x7fb801c04c88 true ----------
On peut voir à partir de coroutine.running que le sous-jacent l'implémentation de la coroutine est un fil.
Lors de la création d'une coroutine, un événement est enregistré dans un nouveau fil de discussion.
Lorsque la reprise est utilisée pour déclencher un événement, la fonction coroutine de create est exécutée. Lorsque le rendement est rencontré, cela signifie suspendre le thread en cours et attendre que la reprise déclenche à nouveau l'événement.
Ensuite, nous analysons un exemple plus détaillé :
function foo (a) print("foo 函数输出", a) return coroutine.yield(2 * a) -- 返回 2*a 的值 end co = coroutine.create(function (a , b) print("第一次协同程序执行输出", a, b) -- co-body 1 10 local r = foo(a + 1) print("第二次协同程序执行输出", r) local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入 print("第三次协同程序执行输出", r, s) return b, "结束协同程序" -- b的值为第二次调用协同程序时传入 end) print("main", coroutine.resume(co, 1, 10)) -- true, 4 print("--分割线----") print("main", coroutine.resume(co, "r")) -- true 11 -9 print("---分割线---") print("main", coroutine.resume(co, "x", "y")) -- true 10 end print("---分割线---") print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine print("---分割线---")
Le résultat de l'exécution de l'exemple ci-dessus est :
第一次协同程序执行输出 1 10 foo 函数输出 2 main true 4 --分割线---- 第二次协同程序执行输出 r main true 11 -9 ---分割线--- 第三次协同程序执行输出 x y main true 10 结束协同程序 ---分割线--- main false cannot resume dead coroutine ---分割线---
L'exemple ci-dessus continue comme suit :
Appelez CV pour réveiller la coroutine. L'opération de reprise renvoie vrai en cas de succès, sinon elle renvoie faux
La coroutine s'exécute
< ; 🎜>- Exécutez l'instruction Yield ;
- Yield raccroche la coroutine et le premier CV revient (Remarque : le rendement revient ici, et les paramètres sont les paramètres du CV ; )
- Reprendre une deuxième fois et réveiller à nouveau la coroutine (Remarque : parmi les paramètres de reprise ici, à l'exception du premier paramètre, les paramètres restants seront utilisés comme paramètres de rendement)
- le rendement revient ;
- La coroutine continue de fonctionner
- Si la coroutine utilisée continue ; pour s'exécuter et continue d'appeler la méthode de reprise une fois terminé, puis Sortie : impossible de reprendre la coroutine morte
Problème producteur-consommateurMaintenant, j'utilise la coroutine de Lua pour résoudre le problème classique producteur-consommateur.
local newProductor function productor() local i = 0 while true do i = i + 1 send(i) -- 将生产的物品发送给消费者 end end function consumer() while true do local i = receive() -- 从生产者那里得到物品 print(i) end end function receive() local status, value = coroutine.resume(newProductor) return value end function send(x) coroutine.yield(x) -- x表示需要发送的值,值返回以后,就挂起该协同程序 end -- 启动程序 newProductor = coroutine.create(productor) consumer()Le résultat de sortie de l'exemple ci-dessus est :
1 2 3 4 5 6 7 8 9 10 11 12 13 ……