Lua学习笔记之协程

协程作为lua脚本语言的重要概念,重要性和C++中的线程、进程类似。

什么是协程

        协程这个概念出现在Go lang和Lua语言之中,协程全称“协同程序”,是一种用户态的轻量级线程。和线程类似,拥有独立的堆栈、局部变量、独立的指针。拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前的寄存器上下文和栈,这种直接操作栈的方法没有内核切换的开销,可以不加锁的访问全局变量,所以上下文切换非常的快。

协同程序(协程)和线程的区别:

        1. 调度方式:线程抢占式,协程非抢占式

        2. 并发性:线程并发,协程是协作式

        3. 内存占用:线程独立的上下文和堆栈,协同程序可以共享,无额外开销

        4. 数据共享:线程可以共享内存空间,协同程序不能,数据隔离性较好

        5. 调试触发:线程通常在调试和错误处理方面更复杂,因为多个线程之间的交互和并发执行可能导致难以调试的问题。协同程序相对简单,因为它们是由程序员显式地控制执行流程的

        总结:线程适用于需要并发执行的场景,例如在多核处理器上利用并行性加快任务的执行速度。而协同程序适用于需要协作和协调的场景,例如状态机、事件驱动编程或协作式任务处理。

相关函数

1.创建 coroutine,返回 coroutine, 参数是一个函数,当和 resume 配合使用的时候就唤醒函数调用

coroutine.create() 

2. 重启 coroutine,和 create 配合使用

resume() 

3. 挂起 coroutine,将 coroutine 设置为挂起状态,这个和 resume 配合使用能有很多有用的效果

yield()  

4. 查看 coroutine 的状态,有三种:dead,suspended,running

status() 

5. 创建 coroutine,返回一个函数,一旦你调用这个函数,就进入 coroutine,和 create 功能重复

wrap()   

6. 返回正在跑的 coroutine,一个 coroutine 就是一个线程,当使用running的时候,就是返回一个 coroutine 的线程号

running()    

实例1

function foo()
    print("协同程序 foo 开始执行")
    local value = coroutine.yield("暂停 foo 的执行")
    print("协同程序 foo 恢复执行,传入的值为: " .. tostring(value))
    print("协同程序 foo 结束执行")
end
-- 创建协同程序
local co = coroutine.create(foo)
-- 启动协同程序
local status, result = coroutine.resume(co)
print(result) -- 输出: 暂停 foo 的执行
-- 恢复协同程序的执行,并传入一个值
status, result = coroutine.resume(co, 42)
print(result) -- 输出: 协同程序 foo 恢复执行,传入的值为: 42

在第一次调用 coroutine.resume 后,协同程序执行到 coroutine.yield 处暂停,并将值返回给主程序。然后,我们再次调用 coroutine.resume,并传入一个值作为协同程序恢复执行时的参数

实例2

-- coroutine_test.lua 文件
-- 创建了一个新的协同程序对象 co,其中协同程序函数打印传入的参数 i
co = coroutine.create(
    function(i)
        print(i);
    end
)
-- 使用 coroutine.resume 启动协同程序 co 的执行,并传入参数 1。协同程序开始执行,打印输出为 1
coroutine.resume(co, 1)   -- 1
-- 通过 coroutine.status 检查协同程序 co 的状态,输出为 dead,表示协同程序已经执行完毕
print(coroutine.status(co))  -- dead
print("----------")
-- 使用 coroutine.wrap 创建了一个协同程序包装器,将协同程序函数转换为一个可直接调用的函数对象
co = coroutine.wrap(
    function(i)
        print(i);
    end
)
co(1)
print("----------")
-- 创建了另一个协同程序对象 co2,其中的协同程序函数通过循环打印数字 1 到 10,在循环到 3 的时候输出当前协同程序的状态和正在运行的线程
co2 = coroutine.create(
    function()
        for i=1,10 do
            print(i)
            if i == 3 then
                print(coroutine.status(co2))  --running
                print(coroutine.running()) --thread:XXXXXX
            end
            coroutine.yield()
        end
    end
)
-- 连续调用 coroutine.resume 启动协同程序 co2 的执行
coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3
-- 通过 coroutine.status 检查协同程序 co2 的状态,输出为 suspended,表示协同程序暂停执行
print(coroutine.status(co2))   -- suspended
print(coroutine.running())
print("----------")

结果:

1
dead
----------
1
----------
1
2
3
running
thread: 0x7fb801c05868    false
suspended
thread: 0x7fb801c04c88    true
----------

生产者消费者模型

local newProductor
function productor()
     local i = 0
     while true do
          i = i + 1
          send(i)     -- 将生产的物品发送给消费者
     end
end

function consumer()
     while true do
          local i = receive()     -- 从生产者那里得到物品
          print(i)
     end
end

function receive()
     local status, value = coroutine.resume(newProductor)
     return value
end

function send(x)
     coroutine.yield(x)     -- x表示需要发送的值,值返回以后,就挂起该协同程序
end

-- 启动程序
newProductor = coroutine.create(productor)
consumer()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值