lua的协程生产者消费者
Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。然而,lua的协程和多线程系统中的线程不同,协程只在显式的调用了yield函数时才会挂起。同一时间也只有一个协程在运行。
- 协程函数:
- coroutine.create(f): 接受一个函数,该函数是协程的主函数,返回一个thread的对象。
- coroutine.resume (co [, val1, ···]):接受一个thread的对象(
coroutine.create的返回)和多个变量。首次运行时,变量被赋予coroutine.create的参数f这个函数,作为入参。如果上次是从coroutine.yield返回的,再次被调度是从coroutine.yield赋值开始执行,因此入参是被赋值到coroutine.yield的赋值开始运行。 - coroutine.yield(...) :接受多个参数,把参数从协程返回并挂起协程。再此调用
coroutine.resume时,会把该函数的参数赋值到接受coroutine.yield的变量,并从挂起处继续执行。
看云风写的这个例子就明白多了:
function foo (a)
print("foo", a)
return coroutine.yield(2*a)
end
co = coroutine.create(function (a,b)
print("co-body", a, b)
local r = foo(a+1)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end)
print("main", coroutine.resume(co, 1, 10))
--[[ 运行结果:
co-body 1 10
foo 2
main true 4
]]
print("main", coroutine.status(co))
--[[
main suspended
]]
print("main", coroutine.resume(co, "rrr"))
--[[
co-body rrr
main true 11 -9
]]
print("main", coroutine.resume(co, "x", "y"))
--[[
co-body x y
main true 10 end
]]
print("main", coroutine.resume(co, "xx", "xy"))
--[[
main false cannot resume dead coroutine
]]
总结:coroutine.resume的返回是coroutine.yield的参数。 coroutine.yield的返回是coroutine.resume的参数。
当调用coroutine.resume时,它会将传入的参数作为当前协程coroutine.yield的返回值,然后恢复该被挂起的协程,使其继续执行。当调用coroutine.yield时,它会将传入的参数作为当前协程的返回值,然后挂起当前协程。
lua的协程,生产者消费者
function receive(prod)
local status, value = coroutine.resume(prod)
return value
end
function send(x)
coroutine.yield(x)
end
function product()
return coroutine.create(function()
while true do
local x = io.read()
if x == "" then break end
send(x)
end
end)
end
function consumer(prod)
while true do
local x = receive(prod)
if not x then
print("status:", coroutine.status(prod))
break
end
print('==>',x)
end
end
consumer(product())
以下是chatgpt的讲解:
Lua协程是一种特殊的线程,它允许在同一个Lua虚拟机中创建多个协程,并在它们之间进行协作式的多任务处理。Lua协程的特点是可以暂停当前协程的执行,切换到另一个协程继续执行,之后再回到原来的协程继续执行。这种切换是由Lua虚拟机控制的,协程本身并没有多线程的并发性,但通过协作式的方式可以实现高效的多任务处理。
Lua协程的实现依赖于Lua的协程库。协程库中提供了一些API来创建协程、启动协程、挂起协程、唤醒协程等操作。其中最常用的API是coroutine.create、coroutine.resume、coroutine.yield和coroutine.status。
举个例子,下面是一个简单的Lua协程示例,它使用协程实现了一个计数器:
function counter()
local count = 0
while true do
count = count + 1
print("count=", count)
coroutine.yield()
end
end
co = coroutine.create(counter)
while true do
coroutine.resume(co)
-- 每次执行时暂停1秒钟
os.execute("sleep 1")
end
这个示例中,我们定义了一个counter函数,它用来计数并打印计数器的值。在函数内部,我们使用了一个无限循环来不断执行计数操作,并通过coroutine.yield()函数暂停协程的执行,等待下一次执行。
在主程序中,我们首先使用coroutine.create函数创建了一个协程,然后在一个无限循环中使用coroutine.resume函数来启动协程,并使用os.execute("sleep 1")函数暂停1秒钟。由于coroutine.resume函数会在每次执行时唤醒协程,并从上次暂停的位置继续执行,所以计数器的值会不断增加。
需要注意的是,Lua协程的使用需要注意协程间的切换和同步问题,否则容易出现死锁或者无法预期的结果。因此,在使用Lua协程时需要仔细考虑各种情况,并严格控制协程之间的同步和通信。