最近在看协程相关的技术点,包括协程的概念,以及在PHP中的实现,可参考之前的内容《PHP中协程实现学习笔记》。
很早就知道Lua支持协程,之前在业务中使用lua的时候也没有了解过协程,完全处于好奇,简单了解了下,很浅的了解,以下是笔记。
一、简单回顾lua代码的执行
0、Linux环境下一般都默认安装的有lua脚步解释器
lua -v Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
1、Mac下可以直接通过brew安装
# 安装 brew install lua # 查看 lua -v Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
2、测试脚本
以下代码保存文件test.lua
print('Hello Lua')
用过lua解释器直接执行即可
lua test.lua Hello Lua
二、Lua协程相关的函数
Lua基础库的子库有一个协程库coroutine,主要包含以下函数
0、coroutine.create(f)
创建一个主体函数为f的新协程。 f必须是一个Lua的函数。 返回这个新协程,它是一个类型为 “thread” 的对象。
1、coroutine.resume(co [, val1, ···])
开始协程co的运行, 或者继续协程co的运行(如果co之前被挂起)。
注:如果协程第一次运行的话,参数var1会作为co的参数传递;如果是继续执行协程的话,参数var1会作为co中上一次yield的返回值。
Tip: resume除了摘要,还有重新开始的意思。
2、coroutine.yield()
挂起正在执行的协程
3、coroutine.status(co)
返回协程co的运行状态: running(运行中)、suspendded(挂起或还没开始运行)、normal(活动的,但并不在运行)、dead(运行完成或异常退出)
4、coroutine.running()
返回两个值: 在运行的协程(返回的是协程的ID), True/False(在主线程中返回True, 否则返回False)
三、Lua协程函数的使用
0、conroutine.resume的返回值
以下代码保存文件test.lua
co = coroutine.create(function (a, b) print("co-body", a, b) local r, s = coroutine.yield(a + b, a - b) print("co-body-after-yield", r, s) return b, "end" end) print("main", coroutine.resume(co, 1, 10)) print("main", coroutine.resume(co, 2, 3))
注:第二次调用coroutine.resume(), 因为执行的是同一个协程,所以是从yield这一行(包含这一行)开始执行。
执行结果
lua test.lua co-body 1 10 main true 11 -9 # yield的参数会作为第一次的返回值 co-body-after-yield 2 3 # 第二次执行,参数作为yield的返回值 main true 10 end
1、conroutine.running()的使用
分别调用coroutine.running()
co = coroutine.create(function (a, b) print("main", coroutine.running()) print("co-body", a, b) local r, s = coroutine.yield(4, 4) print("co-body-after-yield", r, s) return b, "end" end) print("main", coroutine.running()) print("main", coroutine.resume(co, 1, 10)) print("main", coroutine.resume(co, 2, 3))
以上输出结果
main thread: 0x7fd6eb001008 true main thread: 0x7fd6eac06a78 false co-body 1 10 main true 4 4 co-body-after-yield 2 3 main true 10 end
2、更多函数用法
参考:简书-Lua Coroutine详解
四、Lua协程的应用
0、多协程协作运行
co1 = coroutine.create( function() for i = 1, 3 do print('co1_' .. i) -- lua没有sleep函数,调用OS的sleep功能sleep 3s os.execute("sleep " .. tonumber(3)) print(coroutine.running()) coroutine.yield() end end ) co2 = coroutine.create( function() for i = 1, 3 do print('co2_' .. i) print(coroutine.running()) coroutine.yield() end end ) for i = 1, 3 do coroutine.resume(co1) coroutine.resume(co2) end
以上输出
co1_1 thread: 0x7ff264406d88 false co2_1 thread: 0x7ff2644070e8 false co1_2 thread: 0x7ff264406d88 false co2_2 thread: 0x7ff2644070e8 false co1_3 thread: 0x7ff264406d88 false co2_3 thread: 0x7ff2644070e8 false
五、总结&思考
0、Lua中有协程库,使用协程相对比PHP方便和易于理解不少。
1、协程实现并发,个人理解不是不有问题,多个协程是协作运行的,本身就是一个整体, 如果一个协程阻塞了,另外一个协程也会等待执行。比如上面co1 sleep(3)后,co2需要等待。
参考:
https://www.tutorialspoint.com/lua/lua_coroutines.htm
Lua 5.3 参考手册
https://timyang.net/lua/lua-coroutine/Stackoverflow: what-are-lua-coroutines-even-for