Lua 中的协程(coroutine)是一种轻量级的线程,它们共享同一个全局状态,但拥有独立的栈空间。协程允许在 Lua 中实现非阻塞的多任务处理,而无需操作系统的线程调度。这使得协程非常适合用于实现像定时器、网络请求、异步 I/O 等场景。
Lua 的协程使用 coroutine
模块来创建和管理。下面是关于 Lua 协程的一些基本概念和用法,文末给出一个定时器的Demo;
使用 coroutine.create
函数来创建一个新的协程。该函数接受一个函数作为参数,并返回一个协程对象。
lualocal function myCoroutine()
print("Inside coroutine")
end
local co = coroutine.create(myCoroutine)
使用 coroutine.resume
函数来恢复一个已经暂停的协程。当协程被恢复时,它会从上次暂停的位置继续执行,直到遇到 coroutine.yield
或返回。
lua-- 恢复协程
coroutine.resume(co)
coroutine.status
函数用于获取协程的当前状态。可能的状态有 "running"
(协程正在运行)、"suspended"
(协程已暂停)和 "normal"
(协程已完成执行)。
lualocal status = coroutine.status(co)
print(status) -- 输出协程的状态
coroutine.yield
函数用于在协程中主动让出控制权,将执行权交还给调用 coroutine.resume
的代码。这允许实现非阻塞操作,如等待用户输入或等待网络响应。
luafunction myCoroutine()
print("Before yield")
coroutine.yield()
print("After yield")
end
local co = coroutine.create(myCoroutine)
coroutine.resume(co) -- 输出 "Before yield" 并暂停
coroutine.resume(co) -- 恢复并从 yield 后继续,输出 "After yield"
协程可以像普通函数一样返回一个值。当协程返回时,coroutine.resume
会返回 true
以及协程返回的值。
luafunction myCoroutine()
return "Hello from coroutine"
end
local co = coroutine.create(myCoroutine)
local success, result = coroutine.resume(co)
if success then
print(result) -- 输出 "Hello from coroutine"
end
一个协程可以在其生命周期中多次 yield
,每次 yield
都会将控制权交还给调用者,直到协程被再次 resume
。
luafunction myCoroutine()
for i = 1, 3 do
print("Count:", i)
coroutine.yield()
end
end
local co = coroutine.create(myCoroutine)
for i = 1, 3 do
coroutine.resume(co)
end
主线程(或称为“根协程”)也是一个协程,因此它可以使用 coroutine.yield
来让出控制权,尽管这通常不是一个好主意,因为它会暂停整个程序的执行。
coroutine.yield
在一个协程中可以有多个,用于在协程的不同点处暂停和恢复执行。通过合理使用协程,Lua 程序可以实现高效且易于管理的并发行为。
wrap会返回一个function,等价于coroutine.resume(co,timeCnt)
timer = {}
local getTime = os.time
local nextTime = 0
local currentTime = 0
local timeCnt = 0
function timer.IntervalFunc()
while timeCnt > 0 do
while nextTime > currentTime
do
if currentTime ~= getTime() then
currentTime = getTime()
end
end
nextTime = getTime() + 1
timeCnt = timeCnt - 1
print(timeCnt+1)
end
end
function timer.StartTimer(default_vaule)
timeCnt = default_vaule
nextTime = getTime() + 1
-- local co = coroutine.create(timer.IntervalFunc)
-- coroutine.resume(co,timeCnt)
coroutine.wrap(timer.IntervalFunc,timeCnt)()
end
timer.StartTimer(3)
return timer