在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其余昂贵的操做时,注册一个回调到事件循环中,而后当I/O操做完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询全部的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽量的得以执行而不须要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,由于程序员不须要关心线程安全问题。nginx
当前协程繁忙时,主动的放弃CPU资源,等到之后再运行。程序员
最近在研究网络服务框架方面的东西,发现了一个神奇的东西-协程。
一句话说明什么是线程:协程是一种用户态的轻量级线程。
从硬件发展来看,从最初的单核单CPU,到单核多CPU,多核多CPU,彷佛已经到了极限了,可是单核CPU性能却还在不断提高。server端也在不断的发展变化。若是将程序分为IO密集型应用和CPU密集型应用,两者的server的发展以下:
IO密集型应用: 多进程->多线程->事件驱动->协程
CPU密集型应用:多进程–>多线程
若是说多进程对于多CPU,多线程对应多核CPU,那么事件驱动和协程则是在充分挖掘不断提升性能的单核CPU的潜力。编程
不管是线程仍是进程,使用的都是同步进制,当发生阻塞时,性能会大幅度下降,没法充分利用CPU潜力,浪费硬件投资,更重要形成软件模块的铁板化,紧耦合,没法切割,不利于往后扩展和变化。不论是进程仍是线程,每次阻塞、切换都须要陷入系统调用(system call),先让CPU跑操做系统的调度程序,而后再由调度程序决定该跑哪个进程(线程)。多个线程之间在一些访问互斥的代码时还须要加上锁,这也是致使多线程编程难的缘由之一。
现下流行的异步server都是基于事件驱动的(如nginx)。事件驱动简化了编程模型,很好地解决了多线程难于编程,难于调试的问题。异步事件驱动模型中,把会致使阻塞的操做转化为一个异步操做,主线程负责发起这个异步操做,并处理这个异步操做的结果。因为全部阻塞的操做都转化为异步操做,理论上主线程的大部分时间都是在处理实际的计算任务,少了多线程的调度时间,因此这种模型的性能一般会比较好。
总的说来,当单核cpu性能提高,cpu不在成为性能瓶颈时,采用异步server可以简化编程模型,也能提升IO密集型应用的性能。windows
以前说道,协程是一种用户级的轻量级线程。协程拥有本身的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其余地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。所以:
协程能保留上一次调用时的状态(即全部局部状态的一个特定组合),每次过程重入时,就至关于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
在并发编程中,协程与线程相似,每一个协程表示一个执行单元,有本身的本地数据,与其它协程共享全局数据和其它资源。等待线程会抢占cpu,而协程会主动放弃cpu。不论是进程仍是线程,每次阻塞、切换都须要陷入系统调用(system call),先让CPU跑操做系统的调度程序,而后再由调度程序决定该跑哪个进程(线程)。
并且因为抢占式调度执行顺序没法肯定的特色,使用线程时须要很是当心地处理同步问题,而协程彻底不存在这个问题(事件驱动和异步程序也有一样的优势)。安全
以nginx为表明的事件驱动的异步server正在横扫天下,那么事件驱动模型会是server端模型的终点吗?
事件驱动编程的架构是预先设计一个事件循环,这个事件循环程序不断地检查目前要处理的信息,根据要处理的信息运行一个触发函数。其中这个外部信息可能来自一个目录夹中的文件,可能来自键盘或鼠标的动做,或者是一个时间事件。这个触发函数,能够是系统默认的也能够是用户注册的回调函数。
事件驱动程序设计着重于弹性以及异步化上面。许多GUI框架(如windows的MFC,Android的GUI框架),Zookeeper的Watcher等都使用了事件驱动机制。将来还会有其余的基于事件驱动的做品出现。
基于事件驱动的编程是单线程思惟,其特色是异步+回调。
协程也是单线程,可是它能让原来要使用异步+回调方式写的非人类代码,能够用看似同步的方式写出来。它是实现推拉互动的所谓非抢占式协做的关键。网络
协程的好处:多线程
跨平台 跨体系架构 无需线程上下文切换的开销 无需原子操做锁定及同步的开销 方便切换控制流,简化编程模型 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。因此很适合用于高并发处理。
缺点:架构
没法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程须要和进程配合才能运行在多CPU上.固然咱们平常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。 进行阻塞(Blocking)操做(如IO时)会阻塞掉整个程序:这一点和事件驱动同样,可使用异步IO操做来解决