自:http://www.zhihu.com/question/23895384

说到Coroutine,我们必须提到两个更远的东西。在操作系统(os)级别,有进程(process)和线程(thread)两个(仅从我们常见的讲)实际的“东西”(不说概念是因为这两个家伙的确不仅仅是概念,而是实际存在的,os的代码管理的资源)。这两个东西都是用来模拟“并行”的,写操作系统的程序员通过用一定的策略给不同的进程和线程分配CPU计算资源,来让用户“以为”几个不同的事情在“同时”进行“。在单CPU上,是os代码强制把一个进程或者线程挂起,换成另外一个来计算,所以,实际上是串行的,只是“概念上的并行”。在现在的多核的cpu上,线程可能是“真正并行的”。

Coroutine,翻译成”协程“,初始碰到的人马上就会跟上面两个概念联系起来。直接先说区别,Coroutine是编译器级的,Process和Thread是操作系统级的。Coroutine的实现,通常是对某个语言做相应的提议,然后通过后成编译器标准,然后编译器厂商来实现该机制。Process和Thread看起来也在语言层次,但是内生原理却是操作系统先有这个东西,然后通过一定的API暴露给用户使用,两者在这里有不同。Process和Thread是os通过调度算法,保存当前的上下文,然后从上次暂停的地方再次开始计算,重新开始的地方不可预期,每次CPU计算的指令数量和代码跑过的CPU时间是相关的,跑到os分配的cpu时间到达后就会被os强制挂起。Coroutine是编译器的魔术,通过插入相关的代码使得代码段能够实现分段式的执行,重新开始的地方是yield关键字指定的,一次一定会跑到一个yield对应的地方。

对于Coroutine,下面是一个实现的function,里面的片段被yield关键字分成2段:

IEnumerator YieldSomeStuff()
{
yield "hello";
Console.WriteLine("foo!");
yield "world";
}

推进的代码(模拟,非实际):

IEnumerator e = YieldSomeStuff();
while(e.MoveNext())
{
Console.WriteLine(e.Current);
}

以此来推进整个代码片段的分段执行。更详细的分析如 @邓凯的文章里提到。这里只要说明的是,对于Coroutine,是编译器帮助做了很多的事情,来让代码不是一次性的跑到底,而不是操作系统强制的挂起。代码每次跑多少,是可预期的。但是,Process和Thread,在这个层面上完全不同,这两个东西是操作系统管理的。在unity中,StartCoroutine这个方法是个推进器。StartCoroutine会发起类似上面的while循环。因为是while循环,因此,Coroutine本身其实不是“异步的”。

Coroutine在整个Unity系统的位置,下面一张图可以说明:

Unity官方文档里也写到"Normal Coroutine在Update之后"的字眼,如下内容第一行:

Normal coroutine updates are run after the Update function returns. A coroutine is a function that can suspend its execution (yield) until the given YieldInstruction finishes. Different uses of Coroutines:

yield; The coroutine will continue after all Update functions have been called on the next frame.
yield WaitForSeconds(2); Continue after a specified time delay, after all Update functions have been called for the frame
yield WaitForFixedUpdate(); Continue after all FixedUpdate has been called on all scripts
yield WWW Continue after a WWW download has completed.
yield StartCoroutine(MyFunc); Chains the coroutine, and will wait for the MyFunc coroutine to complete first.

由上面的图和文字可以大致猜测,.net虚拟机在每一帧循环中,会依次进入每个编译器预定义好的入口。对于Coroutine,编译器需要产生一些代码,在每次的大循环中,Unity的Update()返回后,保证是yield后的代码被正确调用,这样就形成了我们看到的一个function能分段执行的机制。

协程并不是真正的多线程,下面这段代码在协程中加入死循环,运行就卡住了。

 using UnityEngine;
using System.Collections; public class WWWtest : MonoBehaviour { public string url = "http://images.earthcam.com/ec_metros/ourcams/fridays.jpg";
private WWW www;
public UILabel label;
private uint add = ; void Start()
{
StartCoroutine(downLoad());
StartCoroutine(Add());
add = ;
} // Update is called once per frame
void Update () {
label.text = add.ToString();
} IEnumerator downLoad()
{
yield return null;
Debug.Log("start 1");
yield return new WaitForSeconds();
Debug.Log("");
www = new WWW(url);
Debug.Log("www start");
yield return www;
GetComponent<GUITexture>().texture = www.texture;
Debug.Log("www done");
} IEnumerator Add()
{
while (true) ;
yield return null;
}
}

协程(Coroutine)并不是真正的多线程(转)的更多相关文章

  1. Lua 协程coroutine

    协程和一般多线程的区别是,一般多线程由系统决定该哪个线程执行,是抢占式的,而协程是由每个线程自己决定自己什么时候不执行,并把执行权主动交给下一个线程. 协程是用户空间线程,操作系统其存在一无所知,所以 ...

  2. 协程coroutine

    协程(coroutine)顾名思义就是“协作的例程”(co-operative routines).跟具有操作系统概念的线程不一样,协程是在用户空间利用程序语言的语法语义就能实现逻辑上类似多任务的编程 ...

  3. Unity3D 协程 Coroutine

    协程(Coroutine)的概念存在于很多编程语言,例如Lua.ruby等.而由于Unity3D是单线程的,因此它同样实现了协程机制来实现一些类似于多线程的功能,但是要明确一点协程不是进程或线程,其执 ...

  4. Unity协程(Coroutine)管理类——TaskManager工具分享

    博客分类: Unity3D插件学习,工具分享 源码分析   Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...

  5. (zt)Lua的多任务机制——协程(coroutine)

    原帖:http://blog.csdn.net/soloist/article/details/329381 并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上 ...

  6. qemu核心机制分析-协程coroutine

    关于协程coroutine前面的文章已经介绍过了,本文总结对qemu中coroutine机制的分析,qemu 协程coroutine基于:setcontext函数族以及函数间跳转函数siglongjm ...

  7. Lua的多任务机制——协程(coroutine)

    并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上有这么两种多任务技术,一种是抢占式多任务(preemptive multitasking),它让操作系统来决定 ...

  8. Python并发编程协程(Coroutine)之Gevent

    Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译 ...

  9. Unity协程Coroutine使用总结和一些坑

    原文摘自 Unity协程Coroutine使用总结和一些坑 MonoBehavior关于协程提供了下面几个接口: 可以使用函数或者函数名字符串来启动一个协程,同时可以用函数,函数名字符串,和Corou ...

  10. 【Unity】协程Coroutine及Yield常见用法

    最近学习协程Coroutine,参考了别人的文章和视频教程,感觉协程用法还是相当灵活巧妙的,在此简单总结,方便自己以后回顾.Yield关键字的语意可以理解为“暂停”. 首先是yield return的 ...

随机推荐

  1. 习题:最短路计数(SPFA最短路计数)

    最短路计数(洛谷1144)题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条.输入输出格式输入格式:输入第一行包含2个正整数N,M,为图的顶点数 ...

  2. 网络流 24 题汇总(LOJ 上只有 22 题???)

    太裸的我就不放代码了...(黑体字序号的题表示值得注意) 1.搭配飞行员 [LOJ#6000] 二分图最大匹配. 2.太空飞行计划 [LOJ#6001] 最小割常规套路.输出方案.(注:这题换行符要用 ...

  3. hdu 3721 树的直径

    思路:枚举+树的直径 #include<iostream> #include<cstring> #include<cstdio> #include<algor ...

  4. Python基础教程笔记 第二章

    本章的名字虽然叫列表和元组,但是本章讲的最多的是列表,元祖指讲了很少的一部分.因为元组和列表很多方面都是一样的. 列表和元组的区别:列表可以被修改,元祖不可以被修改. python包含的6种内建序列: ...

  5. kubernetes-dashboard

    1.导入kubernetes-dashboard 镜像 [root@node1 DNS]# docker load < kube-dashboard.tar 6bc90c4dba69: Load ...

  6. ip地址正则表达式

    p = re.compile('^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$') if p.match(dom ...

  7. CSS Modules使用方法

    css modules调研 css模块化解决方案 抛弃css (Radium,jsxstyle,react-style) 利用js来管理样式依赖(css Modules) css模块化面临的问题 全局 ...

  8. 在做展开功能的时候,字体变多了,字体会变大的bug的解决方案

    在没有限制高度的情况下字体会变大,要做展开效果,当然不能限制高度. 解决方案是,加个max-height就可以解决这个问题

  9. Docker学习之Docker Registry

    前言 前面已经学习了怎样通过Dockerfile来构建我们自己的镜像了,但是一个系统可能包含着很多个微服务即有很多个镜像,当镜像越来越多的时候,就必须得有一个地方来管理这些镜像,Docker官方提供了 ...

  10. POJ1716 Integer Intervals

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13984   Accepted: 5943 Description An i ...