lua学习笔记day07-----协同函数和非抢占式多线程

多线程的概念不太明确,所以这一章,还是没有和线程技术对比来理解。

这一章对协同程序的应用和前面提到的过滤器和迭代器不同。
无论是在过滤器和迭代器中,即使有多个协同程序,协同程序之间两两之间都有关系。
比方说,在过滤器中,生成者如果通过函数coroutine.yield(x)将程序挂起,就会把x传递给函数coroutine.resume()作为这个函数的返回值,过滤器拿到这个返回值作为下一个协同函数的条件。

而协同函数在非抢占式多线程中的应用不仅仅如此。一个程序同时保存了多个互不相干的协同程序。然后对多个协同程序不停迭代,在多个协同程序之间切换。
协同程序的特点在于,如果它自己不退出,其他程序将一直没法运行。(除了多线程技术,基本所有的函数都是这样吧)因为协同程序的这个特点,如果多个平行的协同函数在工作,只要有一个协同函数闭塞(卡住了,死循环什么的)。就会导致整个程序停下来。
而协同函数通过yield函数的作用,能保证即使这次协同函数的任务没有完成,也不会卡主不动。可以通过另外超出边界(比如:定时器。)的条件来调用yield来跳出协同程序。把执行权给下面的程序。
下面我们来看一个例子,不要过分关注它是怎么实现数据传递的,而是关注协同程序的工作过程。(这一段代码我没有试过,需要有LuaSocket的库)

function download (host,file)
        local c = assert(socket.connect(host,80))
        local count = 0;
        c:send("GET"..file.."HTTP/1.0\r\n\r\n")
        while true do
                local s,status = receive(c)
                count = count + string.len(s)
                if status == "closed" then break end
        end
        c:colse()
        print(file,count)
end

function receive(connection)
        connection:timeout(0)
        local s,status = connection:receive(2^10)
        if status == "timeout" then
                coroutine.yield(connection)
        end
        return s,status
end

threads = {}
function get (host,file)
        local co = coroutine.create(function ()
                download(host,file)
        end
        )
        table.insert(threads,co)
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(tereads,i)
                                break
                        end
                end
        end
end

do
        host = "www.w3c.org"
        get(host,"/TR/html1401/html40.txt")
        get(host,"/TR/2002/REC-xhtmll-20020801/xhtmll.pdf")
        get(host,"/TR/REC-HTML32.html")
        get(host,"/TR/2000/REC-DOM-Level-2-Core-20001113/Dom2-Core.txt")
        dispatcher()
end

上述代码的关键点在于,当一个协同程序将要闭塞的时候,如何避开闭塞的发生。从而把运行时间交给其他协同程序。

先来看一下各个函数的功能
get函数是用于创建协同函数的,多次调用之后会创建多个协同函数放入到 threads 的表中。
dispatcher函数,对threads的表进行迭代,顺序唤醒协同函数。判断协同yield函数的返回值,来决定是否将这个协同函数移除。确保这张表里所有的协同程序都是还没有完成任务的。
download和receive函数是用于实现下载功能,其中如何下载并不是重点。
重点在于,如果这个协同程序在下载的过程中,一直处于等待状态,这个协同程序就会处于类似闭塞的状态,整个程序就会卡主,一直等待,其他的协同函数无法获得运行的机会。
协同函数通过是否超时来调用yield函数,保证协同函数不会卡主。

这个样子就实现了稳定的非抢占式多线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值