协程(Coroutine)并不是真正的多线程
自: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系统的位置,下面一张图可以说明:
注:图片来自Coroutines++
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)并不是真正的多线程的更多相关文章
- Lua 协程coroutine
协程和一般多线程的区别是,一般多线程由系统决定该哪个线程执行,是抢占式的,而协程是由每个线程自己决定自己什么时候不执行,并把执行权主动交给下一个线程. 协程是用户空间线程,操作系统其存在一无所知,所以 ...
- 协程coroutine
协程(coroutine)顾名思义就是“协作的例程”(co-operative routines).跟具有操作系统概念的线程不一样,协程是在用户空间利用程序语言的语法语义就能实现逻辑上类似多任务的编程 ...
- Unity3D 协程 Coroutine
协程(Coroutine)的概念存在于很多编程语言,例如Lua.ruby等.而由于Unity3D是单线程的,因此它同样实现了协程机制来实现一些类似于多线程的功能,但是要明确一点协程不是进程或线程,其执 ...
- Unity协程(Coroutine)管理类——TaskManager工具分享
博客分类: Unity3D插件学习,工具分享 源码分析 Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...
- (zt)Lua的多任务机制——协程(coroutine)
原帖:http://blog.csdn.net/soloist/article/details/329381 并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上 ...
- qemu核心机制分析-协程coroutine
关于协程coroutine前面的文章已经介绍过了,本文总结对qemu中coroutine机制的分析,qemu 协程coroutine基于:setcontext函数族以及函数间跳转函数siglongjm ...
- Lua的多任务机制——协程(coroutine)
并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上有这么两种多任务技术,一种是抢占式多任务(preemptive multitasking),它让操作系统来决定 ...
- Python并发编程协程(Coroutine)之Gevent
Gevent官网文档地址:http://www.gevent.org/contents.html 基本概念 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译 ...
- Unity协程Coroutine使用总结和一些坑
原文摘自 Unity协程Coroutine使用总结和一些坑 MonoBehavior关于协程提供了下面几个接口: 可以使用函数或者函数名字符串来启动一个协程,同时可以用函数,函数名字符串,和Corou ...
- 【Unity】协程Coroutine及Yield常见用法
最近学习协程Coroutine,参考了别人的文章和视频教程,感觉协程用法还是相当灵活巧妙的,在此简单总结,方便自己以后回顾.Yield关键字的语意可以理解为“暂停”. 首先是yield return的 ...
随机推荐
- 10 个理由让你继续干 IT
1.钱,钱,钱 对,我们努力工作就是为了赚钱,而IT专业人士的努力工作的确得到了很好的补偿.报酬不仅仅是好而已,而是非常棒.根据美国劳工部<2010年美国 就业与报酬情况概览>(表6,PD ...
- Android签名详解
1.什么是签名? 如果这个问题不是放在Android开发中来问,如果是放在一个普通的版块,我想大家都知道签名的含义.可往往就是将一些生活中常用的术语放在计算机这种专业领域,大家就开始迷惑了. ...
- systemtap跟踪C
1.[root@localhost ~]# rpm -qi glibcName : glibc Relocations: (not rel ...
- delphi GetKeyState
GetKeyState(VK_CAPITAL) & 0x0001 0x8000 是键有否按下0x0001 是键的翻转状态 var bF1Down: Boolean;begin bF1Down ...
- Xamarin.iOS,AOT,JIT,Limitations
Since applications on the iPhone using Xamarin.iOS are compiled to static code, it is not possible t ...
- Python可视化库
转自小小蒲公英原文用Python可视化库 现如今大数据已人尽皆知,但在这个信息大爆炸的时代里,空有海量数据是无实际使用价值,更不要说帮助管理者进行业务决策.那么数据有什么价值呢?用什么样的手段才能把数 ...
- Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(4) DateFormat
本章主要介绍DateFormat. DateFormat 介绍 DateFormat 的作用是 格式化并解析“日期/时间”.实际上,它是Date的格式化工具,它能帮助我们格式化Date,进而将Date ...
- 快速将wax配置到项目中进行lua开发
通过Finder浏览到你保存该项目的文件夹.创建三个新的文件夹:wax.scripts和Classes. 第一:首先,下载源代码的压缩包.Wax放在GitHub上(https://github.com ...
- Robotframework(3):使用pycharm编写和运行RF脚本
转自:http://blog.csdn.net/ccggaag/article/details/77529724 我们在使用Robotframework时,经常编写脚本的人或许会不习惯,不过没关系!我 ...
- Raspbian 中国软件源
转自:http://shumeipai.nxez.com/2013/08/31/raspbian-chinese-software-source.html 花了些时间整理了目前最新的树莓派中国大陆地区 ...