[Lua]协调coroutine

协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西++线程与协同程序的主要区别在于++一个具有多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。就是说,一个具有多个协同程序的程序在***任何时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显示地挂起时,它的执行才会暂停***。

一、lua协程函数概览

方法描述
coroutine.create()创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用
coroutine.resume()重启coroutine,和create配合使用
coroutine.yield()挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果
coroutine.status()查看coroutine的状态.注:coroutine的状态有四种:dead,suspend,running,normal
coroutine.wrap()创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复
coroutine.running()返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号

二、 函数详解

1. coroutine.create(f)

创建一个主体函数为 f 的新协程。 f 必须是一个 Lua 的函数。 返回这个新协程,它是一个类型为 “thread” 的对象。不会启动该协程。

local co = coroutine.create(
    function()
        print("in coroutine")
        return "coroutine return"
    end)
print(co)
print(coroutine.resume(co))

Output:
thread: 0039B808
in coroutine
true    coroutine return

2. coroutine.resume(co, [, val1, …])

开始或继续协程co的运行。当第一次执行一个协程时,他会从主函数处开始运行。val1,…这些值会以参数形式传入主体函数。 如果该协程被挂起,resume 会重新启动它; val1, … 这些参数会作为挂起点的返回值。如果协程运行起来没有错误, resume 返回 true 加上传给 yield 的所有值 (当协程挂起), 或是主体函数的所有返回值(当协程中止)。

local co = coroutine.create(
    function (input)
        print("input : "..input)
        local param1, param2 = coroutine.yield("yield")
        print("param1 is : "..param1)
        print("param2 is : "..param2)
        -- return 也会将结果返回给 resume
        return "return"
    end)

--第一次执行,将参数传给input
print(coroutine.resume(co, "function input"))
print("this is main chunk")
--第二次执行,将参数作为yield的返回值,传给param1 param2
print(coroutine.resume(co, "param1", "param2"))

Output:
input : function input
true    yield
this is main chunk
param1 is : param1
param2 is : param2
true    return

coroutine.resume 是在保护模式中运行,如果有任何错误发生, Lua 是不会显示任何错误, 而是 返回 false 加错误消息。同时,这个协程的状态会变成dead。

local co = coroutine.create(
    function()
        print("error test")
        --调用一个空值得属性
        coroutine.yield(a.a)
    end)
-- 返回结果为 false 以及错误信息
print(coroutine.resume(co))
-- 协程的状态变为 dead
print(coroutine.status(co))

Output:
error test
false   K:\lua\coroutine.lua:49: attempt to index global 'a' (a nil value)
dead

3. coroutine.yield(…)

挂起正在调用的协程的执行。 传递给 yield 的参数都会转为 resume 的额外返回值。

local co = coroutine.create(
    function ()
        coroutine.yield("yield1" ,"yield2")
    end)

print(coroutine.resume(co))

Output:
true    yield1  yield2

yield()和resume()的关系如下图

在这里插入图片描述

4. coroutine.status(co)

以字符串形式返回协程 co 的状态:

当协程正在运行(它就是调用 status 的那个) ,返回 “running”;
如果协程调用 yield 挂起或是还没有开始运行,返回 “suspended”;
如果协程是活动的,都并不在运行(即它正在延续其它协程),返回 “normal”;
如果协程运行完主体函数或因错误停止,返回 “dead”。

local co
local co2 = coroutine.create(function() print("3."..coroutine.status(co)) end)
co = coroutine.create(
    function ()
        print("2."..coroutine.status(co))
        coroutine.resume(co2)
        coroutine.yield()
    end)

print("1."..coroutine.status(co))
coroutine.resume(co)
print("4."..coroutine.status(co))
coroutine.resume(co)
print("5."..coroutine.status(co))

Output:
1.suspended
2.running
3.normal
4.suspended
5.dead

5. coroutine.running()

返回当前的协程,如果实在主线程,则返回nil

local co = coroutine.create(
    function () 
        print(coroutine.running()) 
        end)

print(coroutine.running())
coroutine.resume(co)
print(co)

Output:
nil
thread: 003FC9A0
thread: 003FC9A0

** Lua 5.3 有变动 **

6. coroutine.wrap(f)

创建一个主体函数为 f 的新协程。 f 必须是一个 Lua 的函数。 返回一个函数, 每次调用该函数都会延续该协程。 传给这个函数的参数都会作为 resume 的额外参数。 和 resume 返回相同的值, 只是没有第一个布尔量。

local wrap = coroutine.wrap(
    function (input)
        print("input : "..input)
        local param1, param2 = coroutine.yield("yield")
        print("param1 is : "..param1)
        print("param2 is : "..param2)
        -- return 也会将结果返回给 resume
        return "return"
    end)

--第一次执行,将参数传给input
print(wrap("function input"))
print("this is main chunk")
--第二次执行,将参数作为yield的返回值,传给param1 param2
print(wrap("param1", "param2"))

Output:
input : function input
yield
this is main chunk
param1 is : param1
param2 is : param2
return

coroutine.wrap不是保护模式运行,如果发生任何错误,抛出这个错误。

local wrap = coroutine.wrap(
    function()
        print("error test")
        --调用一个空值得属性
        coroutine.yield(a.a)
    end)
-- 返回结果为 false 以及错误信息
print(coroutine.resume(co))

这段代码在运行时,会抛出异常。

三、实例

-- 使用协程实现生产者消费者
function receive()
    local status, value = coroutine.resume(producer)
    return value
end

function send(x)
    coroutine.yield(x)
end

producer = coroutine.create(
    function()
        while true do
            local x = io.read()
            send(x)
        end
    end)

function consumer ()
    while true do
        local x = receive()
        io.write(x, "\n")
    end
end
consumer();
Lua 中,协程(coroutine)是一种特殊的线程,可以在执行过程中挂起和恢复。协程可以用于实现协作式多任务,允许程序在某个点上暂停,并在稍后的时间点继续执行。下面是一些常见的 Lua 协程使用方法: 1. 创建协程:使用 `coroutine.create` 函数来创建一个新的协程。 ```lua local co = coroutine.create(function() -- 协程的执行逻辑 end) ``` 2. 启动协程:使用 `coroutine.resume` 函数来启动或恢复一个协程的执行。 ```lua local success, result = coroutine.resume(co) ``` 3. 挂起协程:使用 `coroutine.yield` 函数来手动挂起一个协程的执行,并返回结果。 ```lua local function foo() print("Hello") coroutine.yield() print("World") end local co = coroutine.create(foo) coroutine.resume(co) -- 输出 "Hello" coroutine.resume(co) -- 输出 "World" ``` 4. 检查协程状态:使用 `coroutine.status` 函数来检查协程的状态。 ```lua local status = coroutine.status(co) ``` 常见的状态有: - "suspended":协程处于挂起状态,即已经创建但尚未执行或已经执行但被挂起。 - "running":当前正在执行的协程。 - "dead":协程已经执行完毕或发生错误导致终止。 以上是一些基本的协程使用方法,还可以使用 `coroutine.wrap` 函数将一个函数转换为协程。在实际应用中,协程可以用于实现状态机、异步操作、迭代器等功能。根据具体需求,可以灵活运用协程的特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值