浅谈我对协程的理解

我心中的协程

最近在研究网络服务框架方面的东西,发现了一个神奇的东西-协程。
一句话说明什么是线程:协程是一种用户态的轻量级线程

一句话并不能完全概括协程的全部,但是起码能让我们对协程这个概念有一个基本的印象。
从硬件发展来看,从最初的单核单CPU,到单核多CPU,多核多CPU,似乎已经到了极限了,但是单核CPU性能却还在不断提升。server端也在不断的发展变化。如果将程序分为IO密集型应用和CPU密集型应用,二者的server的发展如下:
IO密集型应用: 多进程->多线程->事件驱动->协程
CPU密集型应用:多进程-->多线程

如果说多进程对于多CPU,多线程对应多核CPU,那么事件驱动和协程则是在充分挖掘不断提高性能的单核CPU的潜力。
以下的讨论如无特别说明,不考虑cpu密集型应用。

异步 vs 同步

无论是线程还是进程,使用的都是同步进制,当发生阻塞时,性能会大幅度降低,无法充分利用CPU潜力,浪费硬件投资,更重要造成软件模块的铁板化,紧耦合,无法切割,不利于日后扩展和变化。不管是进程还是线程,每次阻塞、切换都需要陷入系统调用(system call),先让CPU跑操作系统的调度程序,然后再由调度程序决定该跑哪一个进程(线程)。多个线程之间在一些访问互斥的代码时还需要加上锁,这也是导致多线程编程难的原因之一。

现下流行的异步server都是基于事件驱动的(如nginx)。事件驱动简化了编程模型,很好地解决了多线程难于编程,难于调试的问题。异步事件驱动模型中,把会导致阻塞的操作转化为一个异步操作,主线程负责发起这个异步操作,并处理这个异步操作的结果。由于所有阻塞的操作都转化为异步操作,理论上主线程的大部分时间都是在处理实际的计算任务,少了多线程的调度时间,所以这种模型的性能通常会比较好。

总的说来,当单核cpu性能提升,cpu不在成为性能瓶颈时,采用异步server能够简化编程模型,也能提高IO密集型应用的性能。

协程 vs 线程

之前说道,协程是一种用户级的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:

协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。

在并发编程中,协程与线程类似,每个协程表示一个执行单元,有自己的本地数据,与其它协程共享全局数据和其它资源。目前主流语言基本上都选择了多线程作为并发设施,与线程相关的概念是抢占式多任务(Preemptive multitasking),而与协程相关的是协作式多任务

不管是进程还是线程,每次阻塞、切换都需要陷入系统调用(system call),先让CPU跑操作系统的调度程序,然后再由调度程序决定该跑哪一个进程(线程)。
而且由于抢占式调度执行顺序无法确定的特点,使用线程时需要非常小心地处理同步问题,而协程完全不存在这个问题(事件驱动和异步程序也有同样的优点)。

我们在自己在进程里面完成逻辑流调度,碰着i\o我就用非阻塞式的。那么我们即可以利用到异步优势,又可以避免反复系统调用,还有进程切换造成的开销,分分钟给你上几千个逻辑流不费力。这就是协程。

协程 vs 事件驱动

以nginx为代表的事件驱动的异步server正在横扫天下,那么事件驱动模型会是server端模型的终点吗?
我们可以深入了解下,事件驱动编程的模型。
事件驱动编程的架构是预先设计一个事件循环,这个事件循环程序不断地检查目前要处理的信息,根据要处理的信息运行一个触发函数。其中这个外部信息可能来自一个目录夹中的文件,可能来自键盘或鼠标的动作,或者是一个时间事件。这个触发函数,可以是系统默认的也可以是用户注册的回调函数。

事件驱动程序设计着重于弹性以及异步化上面。许多GUI框架(如windows的MFC,Android的GUI框架),Zookeeper的Watcher等都使用了事件驱动机制。未来还会有其他的基于事件驱动的作品出现。

基于事件驱动的编程是单线程思维,其特点是异步+回调。
协程也是单线程,但是它能让原来要使用异步+回调方式写的非人类代码,可以用看似同步的方式写出来。它是实现推拉互动的所谓非抢占式协作的关键。

总结

协程的好处:

  • 跨平台
  • 跨体系架构
  • 无需线程上下文切换的开销
  • 无需原子操作锁定及同步的开销
  • 方便切换控制流,简化编程模型
  • 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。

缺点:

  • 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
  • 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序:这一点和事件驱动一样,可以使用异步IO操作来解决
时间: 2024-10-30 20:26:24

浅谈我对协程的理解的相关文章

浅谈Java 对于继承的初级理解_java

概念:继承,是指一个类的定义可以基于另外一个已存在的类,即子类继承父类,从而实现父类的代码的重用.两个类的关系:父类一般具有各个子类共性的特征,而子类可以增加一些更具个性的方法.类的继承具有传递性,即子类还可以继续派生子类,位于上层的类概念更加抽象,位于下层的类的概念更加具体. 1.定义子类: 语法格式 [修饰符] class 子类名 extends 父类名{ 子类体 } 修饰符:public private protected default 子类体是子类在继承父类的内容基础上添加的新的特有内

浅谈对.NET MVC框架的理解

近来我发现有很多关于.NET MVC框架的文章,大家写的也都非常好,也很深刻,我今天也大概看了一下, 顺便用它做了个小留言本,在这里我也来分享一下我的经验,同时也希望大家给出指点,我们大家来共同学习和进步! 第一,我想说一下,对我感触最深的地方就是它对httphandler的处理,学过ASP.NET的人可能都知道,每个页面其实就一个httphandler,我记得那时候刚接触地址映射技术的时候,费了很大的事,既要在配置文件里配置路径和映射规则,又要实现Ihttphandler或者ihttpmodu

浅谈网络营销的几点理解

中介交易 SEO诊断 淘宝客 云主机 技术大厅 1.网络营销,营销是根本,网络是工具.谁笑到最后,看谁的营销功底深厚.贴近客户的.先进的营销理念,具有创意的盈利模式和营销模式,才能让工具的作用发挥得淋漓尽致.好比我们去一个地方要选择不同的交通工具,过去我们只能选择火车.汽车.马车等,现在可以坐更先进更快的飞机.但我们要牢牢记住我们所要到达的目的地,而不要陶醉于坐飞机比坐火车.汽车更爽不能自拔. 2.同样,电子商务,商务是根本,电子是工具. 3.网络营销对每个企业来讲,都是全新的东西,都是不断发展

PHP协程实现过程详解

多进程/线程 最早的服务器端程序都是通过多进程.多线程来解决并发IO的问题.进程模型出现的最早,从Unix 系统诞生就开始有了进程的概念.最早的服务器端程序一般都是 Accept 一个客户端连接就创建一个进程,然后子进程进入循环同步阻塞地与客户端连接进行交互,收发处理数据. 多线程模式出现要晚一些,线程与进程相比更轻量,而且线程之间共享内存堆栈,所以不同的线程之间交互非常容易实现.比如实现一个聊天室,客户端连接之间可以交互,聊天室中的玩家可以任意的其他人发消息.用多线程模式实现非常简单,线程中可

新手站长浅谈对外部链接的理解

我做网站有一段时间了,不论从经验上和SEO上都有了一定的进步,平时也看很多别人的SEO优化心得,其中关于外部链接的最多,因此我结合自己的经验,给大家浅谈我对外部链接的理解. 锚文本多样化:链接的锚文本最好多样化,如果全部都是一个关键词的话,搜索引擎肯定会怀疑,这样容易导出降权和惩罚,合理的应该是关键词为锚文本的占大多数,还应该有少部分其它的锚文本. 相关页面:相关页面的链接投票能力是最大的,会被搜索引擎理解为最具有相关性.可以借助一些高级指令才查找竞争对手都做了什么样的外部链接. 链接位置最好别

理解Python的协程机制-Yield

根据PEP-0342 Coroutines via Enhanced Generators,原来仅仅用于生成器的yield关键字被扩展,成为Python协程实现的一部分.而之所以使用协程,主要是出于性能的考虑:一个活跃的Python线程大约占据8MB内存,而一个活跃线程只使用1KB不到内存.对于IO密集型的应用,显然轻量化的协程更适用. 概述 原来,yield是一个statement,即和return一样的语句,但是在PEP-0342后,yield statement被改造为了yield exp

浅谈PHP拦截器之__set()与__get()的理解与使用方法_php实例

"一般来说,总是把类的属性定义为private,这更符合现实的逻辑. 但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数"__get()"和"__set()"来获取和赋值其属性,以及检查属性的"__isset()"和删除属性的方法"__unset()". 我们为每个属性做了设置和获取的方法,在PHP5中给我们提供了专门为属性设置值和获取值的方法,"__set()"和&qu

浅谈数据库连接

原文:浅谈数据库连接 必须澄清,虽然文章是我总结整理的,但是很多知识的确不是我能研究分析得出来,通过听培训.看书.实践所总结得出,一方面为了给自己备用,以便以后出现问题能解决,另一方面也希望遇到相同问题的朋友能从中得到一些启示.所以文章里面的知识可能会在很多地方都出现. 我们经常会遇到很多连接问题,同时程序员往往也认为连接数据库只需要简单地连接→openconnection→操作→close,但是一个简单的连接动作,背后往往带有很多东西,充分理解,会对开发及管理有很大的帮助,毕竟连不上服务器其他

浅谈面向业务的信息安全审计系统(1)

[51CTO.com 综合报道]近些年来, IT系统发展很快,企业对IT系统的依赖程度也越来越高,就一个网络信息系统而言,我们不仅需要考虑一些传统的安全问题,比如防黑客.防病毒.防垃圾邮件.防后门.防蠕虫等, 但是,随着信息化程度的提高, 各类业务系统也变得日益 复杂,对 业务系统的防护也变得越来越重要,非传统领域的安全治理也变得越来越重要.根据最 新的统计资料,给企业造成的严重攻击中70%是来自于组织中的内部人员,因此,针对业务系统的信息安全治理成为一道难题,审计应运而生.一.为什么需要 面向