如何使用Lua coroutine正确模拟多线程 现有代码运行结果不符合预期
问题根源
你代码的问题出在两个核心设计错误,不需要调用C函数,纯Lua就可以实现需求:
- 你当前写的
Framework.Wait是阻塞式同步等待,进入Wait后会一直占着执行权死循环直到时间到,根本不会主动让出协程,所以第二个协程启动后进入循环调用Wait就卡死了,永远轮不到第三个协程执行。 CreateThread里的yield逻辑完全错误,协程创建阶段不需要主动让出,应该由协程内部的等待逻辑主动触发让出,调度器统一管理所有协程的执行状态。
修复方案
你需要重构等待逻辑和调度逻辑,给每个协程维护下一次可执行的时间戳,Wait时主动yield让出执行权,调度器每次只恢复已经到执行时间的协程:
local Framework = {} local threads = {} -- 存储协程和对应的下次可执行时间 Framework.Wait = function(n) -- 记录当前协程需要等待到的时间戳,主动让出 coroutine.yield(os.clock() + n) end Framework.CreateThread = function(f) -- 把协程和初始可执行时间(立即执行)存入队列 table.insert(threads, { co = coroutine.create(f), next_run = 0 }) end -- 测试代码 Framework.CreateThread(function() print("ok") end) Framework.CreateThread(function() while(true) do Framework.Wait(0.4) print("bot") end end) Framework.CreateThread(function() while(true) do Framework.Wait(0.4) print("got") end end) -- 调度主循环 while(true) do local now = os.clock() for i = #threads, 1, -1 do local thread = threads[i] if now >= thread.next_run then -- 恢复协程,获取返回的下次执行时间 local ok, next_run = coroutine.resume(thread.co) if not ok then -- 协程执行结束,移除队列 table.remove(threads, i) else -- 更新下次执行时间 thread.next_run = next_run or 0 end end end end
验证说明
修改后运行代码就会按照你预期输出:先打印ok,之后交替打印bot和got,完全符合需求。
内容的提问来源于stack exchange,提问作者ayya
相关产品推荐
相关产品推荐

