zoukankan      html  css  js  c++  java
  • 浅谈Lua的Coroutine协程的多"线程"并发模型

    看了一下《Programming in Lua》里的协程程序的运用,总觉得有点像雾里看花一样,捉不到重点,不知道怎么去运用,但在洗澡时灵光一闪,突然想明白了这不只是使用了Reactor(反应时同步时间分派)模式吗。在这里写篇博客跟大家分享一些拙见。

    先贴一下之前看得不怎么懂的源码

    function download (host, file)          -->协同程序
        local c = assert(socket.connect(host, 80))
        local count = 0 -- counts number of bytes read
        c:send("GET " .. file .. " HTTP/1.0\r\n\r\n")
        while true do
            local s, status = receive©
            count = count + string.len(s)
            if status == "closed" then break end
        end
        c:close()
        print(file, count)
    end    
    
    function receive (connection)        -->我把它叫做"中断程序"
        connection:timeout(0) --> do not block
        local s, status = connection:receive(2^10)
        if status == "timeout" then
            coroutine.yield(connection)
        end
        return s, status
    end
    
    threads = {}                               --> list of all live threads
    function get (host, file)                --> 工厂函数
        local co = coroutine.create(function ()
        download(host, file)
        end)
        table.insert(threads, co)           --> insert it in the list
    end
    
    function dispatcher ()                   -->分派器函数    
        while true do
          local n = table.getn(threads)
          if n == 0 then break end  
          for i=1,n do
          local status, res = coroutine.resume(threads[i])
          if not res then    
            table.remove(threads, i)
            break
          end
        end
      end
    end

    首先来看一下

      dispatcher函数实际上充当了Reactor模式中的select和poll/epoll

      get这个工厂函数充当了向分派器注册“线程”(协同程序)的作用

      download与receive这两个函数在Reactor模式中共同起到一个线程的作用

      不同点是:1、以上Lua代码中通过额外的恢复/挂起操作代替了Reactor模式中的分派器检测系统资源来确定线程是否活动

           2、因为分派器与各“线程”(协同程序)的执行实际上都在一个线程中执行,不能利用系统在真正线程之间分时切换,必须手动实现切换。

      Coroutine-协程模型的优点是:

           1、切换上下文的代价比较小。

           2、不需要考虑同步问题。  

           

    实际上按照Reactor模式使用多协程程序很简单

      只需要实现一个全局的分派器,开放注册“线程”的接口。写需要的协同程序(必须包含一个中断条件),并注册到分派器。

      运行分派器就可以实现简单的多线程并发。当然这只是一个最简单的模型,只能在当至少有一个“线程”有数据可读取的时候运行比较良好,如果各个“线程”都处于空闲状态,则分配器会不断轮询线程状态,导致消耗大量时间。

  • 相关阅读:
    php分页问题
    php中memcached的使用
    Linux安装Git
    day06
    day07
    day03
    day05
    day04
    列表的操作
    初识数据类型
  • 原文地址:https://www.cnblogs.com/kirito/p/2828727.html
Copyright © 2011-2022 走看看