Skip to content

协程的实现 ​

协程(coroutines)是一种轻量级的线程,允许在函数之间暂停和恢复执行,从而实现非阻塞的异步编程。它的实现涉及调度、上下文切换和栈管理。

1. 协程的基本概念 ​

协程是一种并发编程机制,在一个线程中执行多个任务,不需要多线程的复杂性。协程可以在执行期间被挂起,并在后续的时间点恢复执行。

三个特性定义了协程的行为。协作式多任务:协程通过显式的暂停和恢复控制任务的执行,避免了传统线程的上下文切换开销。状态管理:协程保持其运行状态,包括局部变量和执行位置。非抢占式:切换完全由程序控制,不会被外部中断。

2. 协程的创建与使用 ​

coroutine.create 接受一个Lua函数,返回一个协程对象。

lua
-- 定义一个协程函数
local function myCoroutine()
    for i = 1, 3 do
        print("协程运行中: " .. i)
        coroutine.yield() -- 暂停协程
    end
end

-- 创建协程
local co = coroutine.create(myCoroutine)

-- 启动协程
coroutine.resume(co) -- 输出: 协程运行中: 1
coroutine.resume(co) -- 输出: 协程运行中: 2
coroutine.resume(co) -- 输出: 协程运行中: 3

暂停与恢复由一对函数完成。coroutine.yield() 暂停协程的执行,把控制权交回调用者,协程在暂停时保存当前的执行状态;coroutine.resume(co, ...) 恢复协程的执行,从上次暂停的地方继续。

lua
local function myCoroutine()
    print("协程开始")
    coroutine.yield()
    print("协程继续")
end

local co = coroutine.create(myCoroutine)
coroutine.resume(co) -- 输出: 协程开始
coroutine.resume(co) -- 输出: 协程继续

3. 协程的状态与生命周期 ​

协程有四种状态。suspended:协程创建后或执行到coroutine.yield()时的暂停状态。running:协程正在执行中。normal:一个协程正在执行、而它又恢复了另一个协程时,该协程处于这种状态。dead:协程已完成执行或发生错误。

coroutine.status(co) 查询协程的当前状态。

lua
local co = coroutine.create(function() coroutine.yield() end)
print(coroutine.status(co)) -- 输出: suspended
coroutine.resume(co)        -- 运行到 yield,协程再次挂起
coroutine.resume(co)        -- yield 返回,函数执行完毕
print(coroutine.status(co)) -- 输出: dead

协程的生命周期包括创建、执行、暂停、恢复和结束,状态在这些阶段之间转换,保证执行上下文被正确管理和恢复。

4. 协程的调度与切换 ​

调度由程序员控制:调用coroutine.resume和coroutine.yield,就显式地决定了协程的执行和暂停时机。

上下文切换在两个方向上发生。暂停时,协程的执行状态(包括栈和局部变量)被保存;恢复时,协程从上次暂停的位置继续执行。

5. 协程的应用场景与最佳实践 ​

应用场景集中在异步编程和任务调度:网络请求或IO操作可以用协程实现而不阻塞主线程,轮询任务或定时任务也可以用它做简单的调度。

实践上有两条经验值得记住。长时间运行的协程会影响程序的响应性,复杂操作适合拆分成多个协程;协程数量过多会带来性能问题,创建和销毁要有节制。

lua
-- 异步任务示例
local function asyncTask()
    for i = 1, 5 do
        print("执行任务: " .. i)
        coroutine.yield() -- 模拟异步操作
    end
end

local co = coroutine.create(asyncTask)
while coroutine.status(co) ~= "dead" do
    coroutine.resume(co)
end

总结 ​

协程在一个线程内实现多任务处理,创建、使用、状态管理和调度都围绕 coroutine 库的几个函数展开,够用来写非阻塞的程序设计。

Hello Lua