首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么lua coroutine实现的我的生产者-消费者模型不能预期地工作?

为什么lua coroutine实现的我的生产者-消费者模型不能预期地工作?
EN

Stack Overflow用户
提问于 2020-10-06 11:36:23
回答 2查看 125关注 0票数 1

我使用coroutine来实现生产者-消费者模型。我的代码如下:

代码语言:javascript
复制
function send(prod, x)
    coroutine.resume(prod, x)
end

function receive()
    local x = coroutine.yield()
    return x
end

function consumer()
    return coroutine.create(function ()
        while true do
            local x = receive()
            io.write(x, "\n")
        end
    end)
end

function producer(prod)
    while true do
        local x = io.read()
        send(prod, x)
    end
end

producer(consumer())

当我运行这段代码时,我得到:

第一个输入消息(“Hello”)消失了。它应该印两次,但现在只印一次。在我看来,我的生产者-消费者模式的流程图应该如下所示:

我搞错了吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-06 12:29:44

输入第一个字符串后,按以下顺序调用函数:

  1. send
  2. consumer
  3. receive
  4. producer.返回的coroutine然后,该程序等待用户输入.

local x = coroutine.yield()local x = receive()producer屈服。目前还没有达到io.write(x, "\n")

用户输入第二行后,如下所示:

  1. send
  2. consumerlocal x = receive()之后恢复并打印第二个输入,
  3. 在其没完没了的循环中,consumer调用receiveproducer生成producer
  4. 等待用户输入。

G 236

以下是更正确的代码:

代码语言:javascript
复制
local function send (x)
    coroutine.yield(x)
end

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

local function producer()
    return coroutine.create(
        function ()
            while true do
                local x = io.read()     -- produce new value
                send(x)
            end
        end
    )
end

function consumer (prod)
    while true do
        local x = receive(prod)   -- get new value
        io.write(x, "\n")          -- consume new value
    end
end
    
consumer(producer())

请注意,这是consumer(producer()),而不是相反。还请注意,producer是协同线,而不是consumer。此外,send收益和receive恢复。

consumer开始节目,一遍又一遍地恢复producer。如果相反,如您的示例所示,consumer直到第二次迭代才准备使用该产品。

UPD:在这里遵循“强制喂食”,即生产者驱动的代码:

代码语言:javascript
复制
local function send (cons, x)
    coroutine.resume (cons, x)
end

local function receive ()
    return coroutine.yield()
end

local function consumer()
    return coroutine.create (
        function (x)
            while true do
                io.write(x, '\n')
                -- corotine.yield() returns the extra arguments of coroutine.resume()
                x = receive()
            end
        end
    )
end

function producer (cons)
    while true do
        local x = io.read() -- make a new value
        send (cons, x)      -- feed the new value
    end
end
    
producer (consumer ())

与作者的示例不同的是,producer sendconsumerreceive则是write

进一步阅读:https://www.lua.org/pil/9.2.html

票数 2
EN

Stack Overflow用户

发布于 2020-10-07 07:58:25

第一次“恢复”协同值时,它不会直接跳转到第一个yield,而是使用给定的参数调用包装函数:

代码语言:javascript
复制
local co = coroutine.wrap(function(aaa)
   print(aaa) -- prints "first"
   print(coroutine.yield()) -- prints "second"
end)

co("first")
co("second")

在您的代码中解决这个问题的简单方法是:

代码语言:javascript
复制
local send, receive =
   coroutine.resume, coroutine.yield

function consumer()
   return coroutine.create(function(x)
      while true do
         io.write(x, "\n")
         x = receive()
      end
   end)
end

function producer(consumer)
   while true do
      local x = io.read()
      send(consumer, x)
   end
end

producer(consumer())
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64225003

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档