Lua学习笔记15:非抢先式的多线程

一、 概念
协同程序提供一种协作式的多线程。每个协同程序都等于是一个线程。一对yield-resume可以将执行权在不同线程之间切换。然而,协同程序与常规的多线程的不同之处在于,协同程序是非抢先式的。就是说,当一个协同程序在运行时,是无法从外部停止它的。只有当协同程序显示地要求挂起时(调用yield),它才会停止。对于有些应用而言,这没有问题,而对于另外一些应用则可能无法接受这种情况。当不存在抢先时,编程会简单许多。无需为同步的bug而抓狂,在程序中所有线程间的同步都是显式的,只需确保一个协同程序在它的临界区域之外调用yield即可。对于这样非抢先式的多线程来说,只要有一个线程调用了一个阻塞操作,整个程序在该操作完成前,都会停止下来。对于大多数应用程序来说,这种行为是无法接受的,这也就导致了许多程序员放弃协同程序,转而使用传统的多线程
下面用一个有趣的方法来解决这个问题:
通过HTTP下载几个远程文件。(该例子中会使用Lua的socket库)
为了下载一个文件,必须先打开一个到该站点的连接,然后发送下载文件的请求并且接收文件,最后关闭连接
1、 require “socket”--加载LuaSocket库
2、local host = "www.w3.org" --定义主机
     local file1 = "/TR/REC-html132.html --下载的文件
3、c = assert(socket.connect(host,80))--连接到该站点的80端口(打开一个TCP连接,连接到该站点的80端口)
4、c:send("GET " .. file1 .. " HTTP/1.0\r\n\r\n) --(连接完成后将返回一个连接对象,可以用这个连接对象来发送文件请求)
5、while true do
         local s,status,partial=c:receive(2^10)
         io.write(s or partial)
         if status=="closed" then 
             break 
         end
      end
--在正常情况下receive函数会返回一个字符串。若发生错误,则会返回nil,并且附加错误代码(status)及出错前读取到的内容partial。当主机关闭连接时,就将其余接收到的内容打印出来,然后退出接收循环。
6、c:close() -- 关闭连接

二、接下来下载几个文件,最笨的办法就是逐个下载,但是太慢。程序大部分时间花费在等待数据的接收上。更明确地说,是将时间花在了receive阻塞调用上。因此如果一个程序可以同时下载所有文件的话,其效率就会快很多了。
当一个连接没有可用数据时,程序便可以从其他的连接处读取数据。
很明显协同程序提供了一种简便的方式来构建这种并发下载。
为每个下载任务创建一个新的线程,只要一个线程无可用数据,它就把控制权转让给一个简单的调度程序。
而这个调度程序则会调用其他下载线程。
在以协同程序来重写程序,先将前面的下载代码重新写:
function receive(connection)
    local s,status,partial = connection:receive(2^10)
    return s or partial,status
end 

function download(host,file)
    local c = assert(socket.connect(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值