Lua学习笔记(六):协程

多线程和协程

多线程是抢占式多任务(preemptive multitasking),每个子线程由操作系统来决定何时执行,由于执行时间不可预知所以多线程需要使用同步技术来避免某些问题。在单核计算机中,同一时刻只有一个线程允许运行,而在多核计算机中,同一时刻可以有多个线程同时运行(比如8核CPU就可以最多让8个线程同时运行)。

协程是协作式多任务(cooperative multitasking),它把决定权交给任务,让它们在自己认为合适的时候自愿放弃执行。协程不是多线程,无论是几核CPU,同一时刻都只会有一个协程在运行。

有意思的是主流的程序语言(如C++、Java、Pascal等)里我们很少能看到协程的身影,但是现在不少动态脚本语言(Lua、Python、Perl)却都提供了协程或与之相似的机制。

Lua本身不支持多线程的,不同线程共享一个State会出问题,但是支持协程。

Lua协程

官方文档:http://www.lua.org/manual/5.2/manual.html#6.2

最简单的示例

下面我们来看一个简单的示例:

 1 --创建一个协程对象, 传入的参数为该协程运行的主函数
 2 co = coroutine.create(
 3 function()
 4      print("step 1")
 5      coroutine.yield()
 6      print("step 2")
 7      coroutine.yield()
 8      print("step 3")
 9 end
10 )
11
12 --运行协程
13 print(coroutine.status(co))
14 coroutine.resume(co)
15 print("main thread code 1")
16 --运行协程
17 print(coroutine.status(co))
18 coroutine.resume(co)
19 print("main thread code 2")
20 --运行协程
21 print(coroutine.status(co))
22 coroutine.resume(co)
23 print("main thread code 2")
24
25 print(coroutine.status(co))

我们先看下运行的结果:

 1 suspended
 2 step 1
 3 main thread code 1
 4 suspended
 5 step 2
 6 main thread code 2
 7 suspended
 8 step 3
 9 main thread code 2
10 dead

我们可以发现,在协程中遇到coroutine.yield()时,该协程的运行会被暂停这时主线程会继续运行,直到调用coroutine.resume方法时对应的协程才会继续运行。当协程的方法运行完毕时该协程也就结束了,state为dead。

带参数和返回的协程

协程是可以带有参数和返回值的,如下:

 1 --创建一个协程对象, 传入的参数为该协程运行的主函数
 2 co = coroutine.create(
 3 function(a, b, c)
 4   local i = 0
 5   print("add", "add", "i:", i)
 6   i = 10
 7   coroutine.yield(a + b, b + c)
 8   print("add", "sub", "i:", i)
 9   i = 100
10   coroutine.yield(a + b, b - c)
11   print("sub", "sub", "i:", i)
12   i = 1000
13   coroutine.yield(a - b, b - c)
14   print("i:", i)
15 end
16 )
17
18 --运行协程
19 state, result1, result2 = coroutine.resume(co, 10, 5, 3)
20 print(state, result1, result2)
21 --运行协程
22 state, result1, result2 = coroutine.resume(co, 100, 50, 30)
23 print(state, result1, result2)
24 --运行协程
25 state, result1, result2 = coroutine.resume(co, 1000, 500, 300)
26 print(state, result1, result2)
27
28 coroutine.resume(co)

运行结果如下:

1 add    add    i:    0
2 true    15    8
3 add    sub    i:    10
4 true    15    2
5 sub    sub    i:    100
6 true    5    2
7 i:    1000

我们看看协程参数和返回值要注意的一点地方:

  1. 参数只有第一次调用时传入有效,后面调用resume传入的参数会被忽略;
  2. 返回值的第一个值为调用是否成功的一个布尔值,如果成功则后跟返回的参数,如果失败则后跟报错的信息;
时间: 2024-08-05 11:14:38

Lua学习笔记(六):协程的相关文章

lua学习笔记12:协程详解和举例

一.coroutine.create创建协程 参数是协程的主函数,返回一个thread对象 co = coroutine.create(function() print("coroutine execute!") end) 二.协程状态 协程有4种状态:挂起(suspended).运行(running).死亡(dead)和正常(normal) coroutine.status(co)返回协程当前的状态 协程创建完之后处于挂起状态 print(coroutine.status(co))

Lua学习笔记(六):函数-续

Lua中的函数是带有词法定界(lexical scoping)的第一类值(first-class values).第一类值指:在Lua中函数和其他值(数值.字符串)一样,函数可以被存放在变量中,也可以存放在表中,可以作为函数的参数,还可以作为函数的返回值.词法定界指:嵌套的函数可以访问他外部函数中的变量.这一特性给Lua提供了强大的编程能力. Lua中关于函数稍微难以理解的是函数也可以没有名字,匿名的.当我们提到函数名(比如print),实际上是说一个指向函数的变量,像持有其他类型的变量一样:

python 3.x 学习笔记17(协程以及I/O模式)

1.协程(微线程)协程是一种用户态的轻量级线程.协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈.因此: 协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置. 2.greenlet模块greenlet是一个用C实现的协程模块,相比与python自带的yield,它可以使你在任意函数之间随意切换,而不需把这个函数先声明为

Lua学习笔记(2) —— 风格

前一篇大概学习了lua常用的语法,都是些刚入门时应该了解的.见这里 Lua学习笔记(1) ——语法 这篇主要记录一些关于lua代码风格的经验,如果不了解它们,还是拿着函数式或传统面向对象的风格去写lua,就永远无法了解lua的精华之所在,弃之所长,取其所短. 1. 函数类型的变量 2. 匿名函数 3. 闭包 4. 表 5. 协程 6. 虚拟机

python之raw_input()(学习笔记六)

python之raw_input()(学习笔记六) 我们经常使用raw_input()读取用户的输入,如下例子所示: >>> name = raw_input('please input your name:'),截图如下: 下面简单说下,raw_input()与if搭配使用,脚本如下: #!/usr/bin/env python # -*- coding:utf-8 -*- birth = raw_input('birth:') if birth < 2000: print '0

Lua学习笔记(七):迭代器与泛型for

1.迭代器与闭包 迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素.在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素. 迭代器需要保留上一次成功调用的状态和下一次成功调用的状态,也就是他知道来自于哪里和将要前往哪里.闭包提供的机制可以很容易实现这个任务.记住:闭包是一个内部函数,它可以访问一个或者多个外部函数的外部局部变量.每次闭包的成功调用后这些外部局部变量都保存他们的值(状态).当然如果要创建一个闭包必须要创建其外部局部变量.所以一个典型的闭包的结构包含

Lua学习笔记9:多文件

一 终端中执行多个文件:-l 加入在文件一中定义了一个变量,在另一文件中输出这个变量,代码如下: --file1.lua num = 100 --file2.lua print(num) 终端输入(注意:不是lua命令行): lua -lfile1 -lfile2 注意:不要加上文件后缀名.lua 二 命令行中加载文件 --lib.lua function norm(x, y) local n2 = x^2 + y^2 return math.sqrt(n2) end function twic

lua学习笔记10:lua简单命令行

前面多次用了命令行,这次就好好学下命令行: 一 格式 lua [options][script][args] 二 具体命令 -e 直接将命令传个lua -l 加载一个文件 -i 进入交互模式 例如,终端输入: lua -e "print(math.sin(12))" lua学习笔记10:lua简单命令行,布布扣,bubuko.com

lua学习笔记11:lua中的小技巧

lua中的小技巧,即基础lua语言本身的特种,进行一个些简化的操作 一 巧用or x = x or v 等价于: if not x then x = v end 如果x为nil或false,就给他赋值为 二 三元运算符实现 a and b or c 类似C语言: a ? b : c and 的运算由优先级高于or lua学习笔记11:lua中的小技巧,布布扣,bubuko.com

Lua学习笔记(三):表的构造

构造器是创建和初始化表的表达式.表是Lua特有的功能强大的东西.最简单的构造函数是{},用来创建一个空表.可以直接初始化数组: 1 days = {"Sunday", "Monday", "Tuesday", "Wednesday", 2 "Thursday", "Friday", "Saturday"} Lua将“Sunday”初始化days[1](第一个元素索引为