代码片段

Lua 中的协程(coroutine)是一种轻量级的线程,它们共享同一个全局状态,但拥有独立的栈空间。协程允许在 Lua 中实现非阻塞的多任务处理,而无需操作系统的线程调度。这使得协程非常适合用于实现像定时器、网络请求、异步 I/O 等场景。

Lua 的协程使用 coroutine 模块来创建和管理。下面是关于 Lua 协程的一些基本概念和用法,文末给出一个定时器的Demo;

1. 创建协程

使用 coroutine.create 函数来创建一个新的协程。该函数接受一个函数作为参数,并返回一个协程对象。

代码语言:javascript代码运行次数:0运行复制
lualocal function myCoroutine()
    print("Inside coroutine")
end

local co = coroutine.create(myCoroutine)

2. 恢复协程

使用 coroutine.resume 函数来恢复一个已经暂停的协程。当协程被恢复时,它会从上次暂停的位置继续执行,直到遇到 coroutine.yield 或返回。

代码语言:javascript代码运行次数:0运行复制
lua-- 恢复协程
coroutine.resume(co)

3. 协程状态

coroutine.status 函数用于获取协程的当前状态。可能的状态有 "running"(协程正在运行)、"suspended"(协程已暂停)和 "normal"(协程已完成执行)。

代码语言:javascript代码运行次数:0运行复制
lualocal status = coroutine.status(co)
print(status)  -- 输出协程的状态

4. 协程中的 yield

coroutine.yield 函数用于在协程中主动让出控制权,将执行权交还给调用 coroutine.resume 的代码。这允许实现非阻塞操作,如等待用户输入或等待网络响应。

代码语言:javascript代码运行次数:0运行复制
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"

5. 协程中的返回

协程可以像普通函数一样返回一个值。当协程返回时,coroutine.resume 会返回 true 以及协程返回的值。

代码语言:javascript代码运行次数:0运行复制
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

6. 多重 yield

一个协程可以在其生命周期中多次 yield,每次 yield 都会将控制权交还给调用者,直到协程被再次 resume

代码语言:javascript代码运行次数:0运行复制
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

7. 协程和主线程

主线程(或称为“根协程”)也是一个协程,因此它可以使用 coroutine.yield 来让出控制权,尽管这通常不是一个好主意,因为它会暂停整个程序的执行。

注意事项

  • 协程应该避免使用过多的内存,因为它们的栈空间是独立的,每个协程都有自己的栈。
  • 协程不应该进行阻塞操作,因为这会阻止整个程序的执行,直到阻塞操作完成。
  • coroutine.yield 在一个协程中可以有多个,用于在协程的不同点处暂停和恢复执行。

通过合理使用协程,Lua 程序可以实现高效且易于管理的并发行为。

8. 协程制作定时器Demo

wrap会返回一个function,等价于coroutine.resume(co,timeCnt)

代码语言:javascript代码运行次数:0运行复制
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
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2024-05-02,如有侵权请联系 cloudcommunity@tencent 删除线程协程lua定时器函数