zoukankan      html  css  js  c++  java
  • chapter9_1 协同程序

      协同程序与线程差不多,也就是一条执行序列:有自己独立的栈、局部变量、指令指针,以及和其他协同程序共享的全局变量和其他大部分东西。

    两者区别在于:一个多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。

    一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,而且正在运行的协同程序只会在其显式地要求挂起时,它的执行才会暂停。

      协同程序是一个强大的解决方案,同样地它的几种主要用法也比较复杂。

      Lua将所有关于协同程序的函数放在一个名为corouting的table里。create函数用于创建新的协同程序,它只有一个参数(函数)。

    create会返回一个thread类型的值,表示新的协同程序。通常create的参数是一个匿名函数:

    co = coroutine.create(function () print("hi") end)
    print(co)        -->thread:0x8071d98

    一个协同程序可以处于4个状态:挂起,运行,死亡,正常。

    可以用函数status检查它的状态:

    print (coroutine.status(co))         -->suspended

    函数resume用于启动一个协同程序的执行,并将其状态由挂起转为运行:

    coroutine.resume(co)         --> hi

    协同程序打印了“hi”就终止了,协同程序的状态处于死亡状态,再也无法返回了。

    协同程序的真正强大之处在于函数yield的使用上,它可以让一个运行中的程序挂起,而之后再恢复它的运行。

    co = coroutine.create(function ()
                    for i = 1,10 do
                        print("co",i)
                        coroutine.yield()
                    end
          end)

    现在唤醒这个协同程序时,它就会开始执行,直到第一个yield:

    coroutine.resume(co)        -->co  1

    此时检查它的状态,就会看到它处于挂起状态。可以再次恢复其运行。

    从协同程序的角度看,所有在它挂起时发生的轰动都发生在yield调用中。

    当恢复协同程序的执行时,对于yield的调用才最终返回。然后协同程序继续它的执行,直到下一个yield调用或执行结束:

    coroutine.resume(co)        -->co  2
    coroutine.resume(co)        -->co  3
    ...
    coroutine.resume(co)        -->co  10
    coroutine.resume(co)        --什么都不打印

    到最后一次调用,协同程序已经返回。这时协同程序处于死亡状态。再resume就会返回false及一条错误消息:

    print (coroutine.resume(co))
    --> false    cannot resume dead coroutine

    请注意,resume是在保护模式中运行的。因此如果在一个协同程序的执行中发生任何错误

    lua是不会显示错误消息的,而是将执行权返回给resume调用。

    当一个协同程序A唤醒另一个协同程序B时,A就处于一个特殊状态,不是挂起,也不是运行。称为正常状态。

    Lua的协同程序还有一个很有用的机制,可以通过一对resume-yield来交换数据。

    第一次resume时,没有yield在等待它,所有传给resume的额外参数都将视为协同程序主函数的参数

    co = coroutine.create(function (a,b,c)
                print("co",a,b,c+2 )
            end)
    coroutine.resume(co,1,2,3)        -->co   1  2  5

    在resume的返回内容中,第一个值为true表示没有错误,而后面所有的值都是对应yield转入的参数

    co = coroutine.create(function(a,b)
            coroutine.yield(a+b,a-b)
            end)
    print(coroutine.resume(co,20,10))  -->true  30  10

    与此对应的是,yield返回的额外值就是对应resume传入的参数

    co = coroutine.create(function (x)
                print("co1",x)
                print("co2",coroutine.yield())
            end)
    coroutine.resume(co,"hi")        -->co1  hi
    coroutine.resume(co,4,5)         -->co2  4  5

    最后,当一个协同程序结束时,它的主函数所返回的值都将作为对应resume的返回值

    co = coroutine.create(function ()
                    return 6,7
            end)
    print(coroutine.resume(co))     -->true  6 7

    很少在一个程序中使用所有这些功能,但是每种功能各有其用途。

    Lua提供的是一种“非对称的协同程序”。也就是Lua提供了两个函数来控制协同程序,一个用于挂起,一个用于恢复。

    而其它一些语言提供的则是“对称的协同程序”,切换执行权都只有一个函数。

    一个协同程序只能在它没有调用其他函数时,才可以挂起执行。换句话说,只有协同程序的主函数才能调用类似于yield这样的函数。

  • 相关阅读:
    MVC提交时验证
    远程计划任务管理
    教你一步一步部署.net免费空间OpenShift系列之四------绑定域名、使用CDN加速
    启用IIS7报错功能
    教你一步一步部署.net免费空间OpenShift系列之三------上传ASP.net程序
    教你一步一步部署.net免费空间OpenShift系列之二------创建应用
    Spring SimpleJdbcOperations 批量更新
    c#获取已安装的所有NET版本
    (转载)数据库效率提高的方案
    linux两台服务器之间文件/文件夹拷贝
  • 原文地址:https://www.cnblogs.com/daiker/p/5819031.html
Copyright © 2011-2022 走看看