May 12, 2021 Lua
The Lua co-program (coroutine) is similar to threads in that it has a separate stack, separate local variables, independent instruction pointers, and shares global variables and most of other things with other co-programs.
Synergy is a very powerful feature, but it's also complicated to use.
The main difference between a thread and a collaborating program is that a program with multiple threads can run several threads at the same time, while a co-program needs to work with each other.
Only one co-program is running at any one specified time, and the running co-program is suspended only if explicitly required to suspend.
The co-worker is a bit like a synchronized multithreaded, and a few threads waiting for the same thread lock are a bit like a collaboration.
Method | Describe |
---|---|
coroutine.create() | Create coroutine and return coroutine, the argument is a function that wakes up when used in conjunction with resume |
coroutine.resume() | Restart the coroutine and use it with create |
coroutine.yield() | Suspend the coroutine and set the coroutine to the pending state, which works with resume to have a lot of useful effects |
coroutine.status() |
View the status of coroutine
Note: There are three states of coroutine: dead, suspend, running, and when this is the case, please refer to the following program |
coroutine.wrap() | Create a coroutine, return a function, and once you call it, you go into the coroutine, and the create function repeats |
coroutine.running() | Return to the running coroutine, a coroutine is a thread, when using running, is to return a corouting thread number |
-- coroutine_test.lua 文件 co = coroutine.create( function(i) print(i); end ) coroutine.resume(co, 1) -- 1 print(coroutine.status(co)) -- dead print("----------") co = coroutine.wrap( function(i) print(i); end ) co(1) print("----------") 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) --1 coroutine.resume(co2) --2 coroutine.resume(co2) --3 print(coroutine.status(co2)) -- suspended print(coroutine.running()) --nil print("----------")
The output of the above examples is:
1 dead ---------- 1 ---------- 1 2 3 running thread: 0x7fb801c05868 false suspended thread: 0x7fb801c04c88 true ----------
As can be seen from coroutine.running, the coroutine implementation at the bottom is a thread.
When create a coroutine is registered in a new thread, an event is registered.
When a resume is used to trigger an event, the create's coroutine function is executed, and when yield is encountered, it suspends the current thread, waiting for the resume to trigger the event again.
Let's then analyze a more detailed example:
function foo (a) print("foo 函数输出", a) return coroutine.yield(2 * a) -- 返回 2*a 的值 end co = coroutine.create(function (a , b) print("第一次协同程序执行输出", a, b) -- co-body 1 10 local r = foo(a + 1) print("第二次协同程序执行输出", r) local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入 print("第三次协同程序执行输出", r, s) return b, "结束协同程序" -- b的值为第二次调用协同程序时传入 end) print("main", coroutine.resume(co, 1, 10)) -- true, 4 print("--分割线----") print("main", coroutine.resume(co, "r")) -- true 11 -9 print("---分割线---") print("main", coroutine.resume(co, "x", "y")) -- true 10 end print("---分割线---") print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine print("---分割线---")
The output of the above examples is:
第一次协同程序执行输出 1 10 foo 函数输出 2 main true 4 --分割线---- 第二次协同程序执行输出 r main true 11 -9 ---分割线--- 第三次协同程序执行输出 x y main true 10 结束协同程序 ---分割线--- main false cannot resume dead coroutine ---分割线---
The above examples are followed by the following:
The powerful fit between resume and yield is that resume is in the main course, which brings the external state (data) into the collaboration program, and yield returns the internal state (data) to the master.
Now I'm using Lua's collaborative program to solve the classic producer-consumer problem.
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()
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()
The output of the above examples is:
1 2 3 4 5 6 7 8 9 10 11 12 13 ……