如何使用协程正确模拟线程

我正在尝试创建一个可以将多个线程协作工作的工具。有问题吗?代码不能协同工作,只能依次工作。我编写了以下代码

local Framework = {}
local threads = {}

local function has_value (tab, val)
    for index, value in ipairs(tab) do
        if value == val then
            return true
        end
    end

    return false
end

Framework.Wait = function(n)
  local t0 = os.clock()
   while os.clock() - t0 <= n do
   end
end

Framework.CreateThread = function(f)
  local thread = coroutine.create(f)
  table.insert(threads, thread)
  local index={}
  for k,v in pairs(threads) do
     index[v] = k
  end
  if threads[index[thread] + 1] then
    coroutine.yield(threads[index[thread] + 1])
  end
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
  Framework.Wait(0.1)
  for i = 1, #threads do
      coroutine.resume(threads[i])
  end
end

但是,它没有按照我的期望返回结果。以下是它返回的结果:

lua test.lua
ok
bot
bot
bot
bot
bot
bot
bot
bot
bot

以下是我期望的结果:

ok
bot
got
bot
got
bot
got
....

或者我需要使用 C 函数来实现吗?我无法在脑海中构思出创建算法。

原文链接 https://stackoverflow.com/questions/69293014

点赞
stackoverflow用户2858170
stackoverflow用户2858170
while(true) do
    Framework.Wait(0.4)
    print("bot")
 end

你陷入了这个无限循环中。它会一直等待并打印。你需要yield。

2021-09-23 07:27:12
stackoverflow用户10391157
stackoverflow用户10391157

协程不会并行运行,因此需要使用 yield 方法让下一个协程运行。使用 Framework.Wait() 方法可以达到完美的 yield 效果。我们 yield 并返回要等待的时间。线程调度器 (注意更改)则会处理时间。

local Framework = {}
local threads = {}
local sleepUntil = {}

Framework.Wait = function(n)
  coroutine.yield(n)
end

Framework.CreateThread = function(f)
  local thread = coroutine.create(f)
  table.insert(threads, thread)
  table.insert(sleepUntil, 0)
  local index={}
  for k,v in pairs(threads) do
     index[v] = k
  end
  if threads[index[thread] + 1] then
    coroutine.yield(threads[index[thread] + 1])
  end
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
  for i = 1, #threads do
    if os.clock() > sleepUntil[i] then
      local continue, sleep = coroutine.resume(threads[i])
      if continue and sleep then
        sleepUntil[i] = os.clock() + sleep
      end
     end
  end
end
2021-09-23 13:40:08