在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一个关于协同程序的经典示例是“生产者-消费者”问题。这其中涉及到两个函数,一个函数不断地产生值(比如从一个文件中读取值),另一个则不断地消费这些值(比如将这些值写到另一个文件)。通常,这两个函数大致是这样的: function producer () while true do local x = io.read() -- 产生新的值 send(x) -- 发送给消费者 end end function consumer () while true do local x = receive() -- 从生产者接收值 io.write(x, "\n") -- 消费新的值 end end 这里有一个问题是如何将send与receive匹配起来。这是一个典型的“谁具有主循环(who-has-the-main-loop)”的问题。由于生产者和消费者都处于活动状态,它们个字具有一个朱迅欢,并且都将对方视为一个磕掉用的服务。 function receive () local status, value = coroutine.resume(producer) return value end function send (x) coroutine.yield(x) end 因此,生产者现在一定是一个协同程序: producer = coroutine.create( function () while true do local x = io.read() -- 产生新的值 send(x) -- 发送给消费者 end end end) 在这种设计中,程序通过调用消费者来启动。当消费者需要一个新值时,它唤醒生产者。生产者返回一个新值后停止运行,并等待消费者的自此唤醒。将这种设计称为“消费者驱动(consumer-driven)”。 function receive (prod) local status, value = coroutine.resume(prod) return value end function send (x) coroutine.yield(x) end function producer () return coroutine.create(function () while true do local x = io.read() -- 产生新值 send(x) end end) end function filter (prod) return coroutine.create(function () for line = 1,math.huge do local x = receive(prod) -- 获取新值 x = string.format("%5d %s", line, x) send(x) -- 将新值发送给消费者 end end) end function consumer (prod) while true do local x = receive(prod) io.write(x, "\n") end end 接下来创建运行代码就非常简单了,只需将这些函数串联起来,然后启动消费者: p = producer() f = filter(p) consumer(f) 或者,更简单地写为: consumer(filter(producer())) 如果接触过UNIX的pipe(管道),那么本例的内容就不会很陌生。毕竟,协同程序也是一种(非抢先的)多线程。在pipe中没想任务都在各自独立的进程中运行,而在协同程序中每项任务都在各自独立的协同程序中运行。pipe在writer(消费者)与reader(生产者)之间提供一个缓冲器,因此它们的运行速度允许存在一定差异。值得注意的是,在pipe中进程间的切换代价恨到。而在协同程序中,切换代价则小得多,因此writer和reader可以彼此协作地运行。 ---------- 完整程序示例: function receive (prod) local status, value = coroutine.resume(prod) return value end function send (x) coroutine.yield(x) end function producer () return coroutine.create(function () while true do local x = io.read() -- 产生新值 send(x) end end) end function filter (prod) return coroutine.create(function () for line = 1,math.huge do local x = receive(prod) -- 获取新值 x = string.format("%5d %s", line, x) send(x) -- 将新值发送给消费者 end end) end function consumer (prod) while true do local x = receive(prod) io.write(x, "\n") end end p = producer() f = filter(p) consumer(f) -- consumer(filter(producer()))
|
请发表评论