博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Lua之协同程序(coroutine)
阅读量:6153 次
发布时间:2019-06-21

本文共 2524 字,大约阅读时间需要 8 分钟。

什么是协同(coroutine)?

Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。

协同是非常强大的功能,但是用起来也很复杂。

线程和协同程序区别

线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。

在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。

协同程序有点类似同步的多线程,在等待同一个线程锁的几个线程有点类似协同。

基本语法

方法 描述
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的线程号
function foo(a)	print("foo 函数输出 ",a)	-- 返回2*a的值	return coroutine.yield(2 * a)endco = coroutine.create(function (a,b)--cp-body 1 10	print("第一次协同程序执行输出 ", a,b)	local r = foo(a + 1)	print("第二次协同程序输出 ",r)--a,b的值为第一次调用协同程序时传入	local r,s = coroutine.yield(a+b, a - b)	print("第三次协同程序输出 ",r,s)	--b的值为第二次调用协同程序时传入	return b,"结束协同程序"end)print("---------------分割线---------------");print("main", coroutine.resume(co,1,10))  --true 4print("协同程序的状态: ",coroutine.status(co))print("---------------分割线---------------");print("main", coroutine.resume(co,"r"))  --true 4print("协同程序的状态: ",coroutine.status(co))print("---------------分割线---------------");print("main", coroutine.resume(co,"x","y"))  --true 4print("协同程序的状态: ",coroutine.status(co))print("---------------分割线---------------");print("main", coroutine.resume(co,"x","y"))  --true 4print("协同程序的状态: ",coroutine.status(co))print("---------------分割线---------------");

以上实例接下如下:

  • 调用resume,将协同程序唤醒,resume操作成功返回true,否则返回false;

  • 协同程序运行;

  • 运行到yield语句;

  • yield挂起协同程序,第一次resume返回;(注意:此处yield返回,参数是resume的参数)

  • 第二次resume,再次唤醒协同程序;(注意:此处resume的参数中,除了第一个参数,剩下的参数将作为yield的参数)

  • yield返回;

  • 协同程序继续运行;

  • 如果使用的协同程序继续运行完成后继续调用 resume方法则输出:cannot resume dead coroutine

resume和yield的配合强大之处在于,resume处于主程中,它将外部状态(数据)传入到协同程序内部;而yield则将内部的状态(数据)返回到主程中。

=============================================================================

生产者-消费者问题

现在我就使用Lua的协同程序来完成生产者-消费者这一经典问题。

local newProductorfunction productor()	local i= 0;	while true do		i = i + 1;		send(i) -- 将生产的物品发给消费者	endendfunction consume()	i = 0	while (i < 10) -- 控制大小	do		i = i + 1		local i = receive() --从生产者那里得到物品		print(i)	endendfunction receive()	local status , value = coroutine.resume(newProductor)	return valueendfunction send(x)--x表示需要发生的值,值返回以后,就挂起该协同程序	coroutine.yield(x)end-- 启动程序newProductor = coroutine.create(productor)consume()

转载地址:http://sdffa.baihongyu.com/

你可能感兴趣的文章
正则表达式的语法规则
查看>>
C#一个关于委托和事件通俗易懂的例子
查看>>
类似于SVN的文档内容差异对比工具winmerge
查看>>
Cause: java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist
查看>>
quratz线程
查看>>
execnet: rapid multi-Python deployment
查看>>
windows修改3389端口
查看>>
关于JavaScript词法
查看>>
FreeSwitch中的会议功能(4)
查看>>
MySQL中创建用户分配权限(到指定数据库或者指定数据库表中)
查看>>
php函数总结
查看>>
Java 对象的封装,继承,抽象,接口写法
查看>>
Java抽象类与接口的区别
查看>>
换教室
查看>>
Oracle笔记(4):一个存储过程编写及C#调用
查看>>
第二轮冲次会议第二次
查看>>
【转】Erlang代码片段
查看>>
BZOJ 3434 [Wc2014]时空穿梭
查看>>
typescript+react+antd基础环境搭建
查看>>
好用的meta标签
查看>>