Lua的协同程序

简介:

Lua是一种简单,可扩展,可移植及高效的脚本语言。在嵌入式系统,移动设备,web服务器,游戏等方面都能见到它的身影。lua其中最吸引人的一点事它能很方便地与C语言或者其他语言。

这里说的是lua语言中的协同程序(coroute),也有人翻译成为协作程序

基本函数和语法

coroutine就是lua的协同程序


先讲一下coroutine的语法:

coroutine.create( )

创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用

coroutine.resume( )

重启coroutine,和create配合使用

coroutine.yield()

挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果

coroutine.status( )

查看coroutine的状态

注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序

coroutine.wrap(

创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复

coroutine.running()

返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号

使用下面的程序来了解一下这几个函数的基本用法:

co = coroutine.create(
     function (i)
         print (i);
     end
)
 
coroutine.resume(co, 1)   -- 1
print (coroutine.status(co))  -- dead
 
print ( "----------" )
 
co = coroutine.wrap(
     function (i)
         print (i);
     end
)
 
co(1)
 
print ( "----------" )
 
co2 = coroutine.create(
     function ()
         for  i=1,10 do
             print (i)
             if  i == 3 then
                 print (coroutine.status(co2))  --running
                 print (coroutine.running()) --thread:XXXXXX
             end
             coroutine. yield ()
         end
     end
)
 
coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3
 
print (coroutine.status(co2))   -- suspended
print (coroutine.running())   --nil
 
print ( "----------" )

返回数据:

image

coroutine.running就可以看出来,coroutine在底层实现就是一个线程。当create一个coroutine的时候就是在新线程中注册了一个事件。当使用resume触发事件的时候,create的coroutine函数就被执行了,当遇到yield的时候就代表挂起当前线程,等候再次resume触发事件。

分析学习coroutine的时候经常遇到的一个程序

源程序可以看这里

我稍微做了点修改,增加了一下分隔符:

function foo (a)
     print( "foo" , a)  -- foo 2
     return  coroutine.yield(2 * a) -- return : a , b
end
 
co = coroutine.create(function (a , b)
     print( "co-body" , a, b) -- co-body 1 10
     local r = foo(a + 1)
     
     print( "co-body2" , r)
     local r, s = coroutine.yield(a + b, a - b)
     
     print( "co-body3" , r, s)
     return  b, "end"
end)
        
print( "main" , coroutine.resume(co, 1, 10)) -- true , 4
print( "------" )
print( "main" , coroutine.resume(co, "r" )) -- true  11 -9
print( "------" )
print( "main" , coroutine.resume(co, "x" , "y" )) -- true  10 end
print( "------" )
print( "main" , coroutine.resume(co, "x" , "y" )) -- false  cannot resume dead coroutine
print( "------" )

这个程序返回:

image

很神奇,也很让人看不懂


先理解下下面几点:

  1. resume一定是在主线程的,yield是在子线程(coroutine)的
  2. resume可以带参数
    当coroutine是suspend状态的时候,参数是作为coroutine的参数传入的
    当coroutine是suspend状态的时候,参数是作为coroutine的参数传入的
  3. resume返回值有两种情况
    • 当coroutine是suspend状态的时候,返回是是bool [yield params]
      bool是这个resume操作是否成功
      yield params是当前coroutine的yield的参数
    • 当coroutine是dead状态的时候,返回值是bool [function return]
      bool是这个resume操作是否成功
      yield params是当前coroutine的yield的参数

先对照上面几条看一个简单的例子:

co = coroutine.create(
     function (a , b)
         print( "params" , a, b)
         return  coroutine.yield(3, 3)
     end
)
coroutine.resume(co, 1, 2);
print(coroutine.resume(co, 4, 5))

image

理解完上面这个程序,再看看coroutine2的程序,这里把每个输出执行了哪些步骤列出来了:

  1. print("main", coroutine.resume(co, 1, 10)) 执行了:
    print("co-body", 1, 10)
    print("foo", 2)
    coroutine.resume(co, 1, 10) 返回 true, 4 (!!这里的4是yield的参数)
    print("main", true, 4)
  2. print("main", coroutine.resume(co, "r")) 执行了:
    foo(a) 返回了 "r" (这是由yield返回的)
    print("co-body2", "r")
    coroutine.resume(co, "r") 返回 true, 11 -9 (!!这里的a和b还是用1和10计算的)
    print("main" , true, 11 -9)
  3. print("main", coroutine.resume(co, "x", "y"))执行了:
    local r, s = coroutine.yield(a + b, a - b) r和s值为x和y
    print("co-body3", "x", "y")
    return b, "end" //此时coroutine线程结束,为dead状态
    coroutine.resume(co, "x", "y") 返回值为 true 10 end
    print("main" , true 10 end)
  4. print("main", coroutine.resume(co, "x", "y"))执行了:
    由于coroutine.resume(co, "x", "y")已经dead了,所以这里返回false





本文转自轩脉刃博客园博客,原文链接:http://www.cnblogs.com/yjf512/archive/2012/05/28/2521412.html,如需转载请自行联系原作者
相关文章
|
1月前
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
Lua的面向对象编程、协同线程与协同函数的概念和使用,以及Lua文件I/O操作的基本方法。
28 4
lua面向对象(类)和lua协同线程与协同函数、Lua文件I/O
lua语言——协同程序(协程)
lua语言——协同程序(协程)
136 0
Lua协同程序(协程)
Lua协同程序(协程)
331 0
Lua协同程序(协程)
|
6月前
|
存储 NoSQL Redis
Redis的Lua脚本有什么作用?
Redis Lua脚本用于减少网络开销、实现原子操作及扩展指令集。它能合并操作降低网络延迟,保证原子性,替代不支持回滚的事务。通过脚本,代码复用率提高,且可自定义指令,如实现分布式锁,增强Redis功能和灵活性。
249 1
|
1月前
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
29 2
|
5月前
|
消息中间件 NoSQL Java
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
Redis系列学习文章分享---第六篇(Redis实战篇--Redis分布式锁+实现思路+误删问题+原子性+lua脚本+Redisson功能介绍+可重入锁+WatchDog机制+multiLock)
227 0
|
2月前
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
3月前
|
存储 NoSQL Redis
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决
Tair的发展问题之在Redis集群模式下,Lua脚本操作key面临什么问题,如何解决