`
wx1568037608
  • 浏览: 33415 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

协程

 
阅读更多

协程,又称微线程,纤程。英文名Coroutine。

协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。

子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。

所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。

子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。

协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。

注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点类似CPU的中断。比如子程序A、B:

def A():
    print '1'
    print '2'
    print '3'

def B():
    print 'x'
    print 'y'
    print 'z'

假设由协程执行,在执行A的过程中,可以随时中断,去执行B,B也可能在执行过程中中断再去执行A,结果可能是:

1
2
x
y
3
z

但是在A中是没有调用B的,所以协程的调用比函数调用理解起来要难一些。

看起来A、B的执行有点像多线程,但协程的特点在于是一个线程执行,那和多线程比,协程有何优势?

最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

第二大优势就是不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。

因为协程是一个线程执行,那怎么利用多核CPU呢?最简单的方法是多进程+协程,既充分利用多核,又充分发挥协程的高效率,可获得极高的性能。

Python对协程的支持还非常有限,用在generator中的yield可以一定程度上实现协程。虽然支持不完全,但已经可以发挥相当大的威力了。

来看例子:

传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。

如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,切换回生产者继续生产,效率极高:

import time

def consumer():
    r = ''
    while True:
        n = yield r
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        time.sleep(1)
        r = '200 OK'

def produce(c):
    c.next()
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()

if __name__=='__main__':
    c = consumer()
    produce(c)

执行结果:

[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

注意到consumer函数是一个generator(生成器),把一个consumer传入produce后:

  1. 首先调用c.next()启动生成器;

  2. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;

  3. consumer通过yield拿到消息,处理,又通过yield把结果传回;

  4. produce拿到consumer处理的结果,继续生产下一条消息;

  5. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

最后套用Donald Knuth的一句话总结协程的特点:

“子程序就是协程的一种特例。”

分享到:
评论

相关推荐

    Swoole2.0原生协程高性能开发实践

    此外,文档还涉及了协程实践中的一些关键概念,比如“Generator双向通信”,即Generator可以和协程互相通信,使得通过yield控制的代码块可以恢复执行。 在协程的开发实践中,开发者需要关注的点包括开发效率、内存...

    C++开源协程库libco-原理与应用

    ### C++开源协程库libco-原理与应用 #### 导论 随着现代软件开发对高并发和高性能的需求日益增长,使用C++编写高性能网络服务器成为了一个热门话题。然而,传统的C++网络编程通常涉及复杂的事件驱动模型,如基于`...

    C++ 开源协程库 libco——原理及应用1

    【C++ 开源协程库 libco——原理及应用】 协程,作为一种轻量级的并发机制,近年来在编程领域中越来越受到重视。不同于传统的线程模型,协程不涉及昂贵的上下文切换,而是通过用户空间的协作来实现并发执行。C++ ...

    c++ libgo 多协程ppt

    C++中的多协程技术,特别是结合Libgo库的使用,是现代并发编程的重要手段。在C++中,多线程常用于实现并发,但线程间的上下文切换和同步锁带来的性能开销是其主要痛点。而协程,作为轻量级的执行单元,可以在单线程...

    Delphi 版 Coroutines(协程)

    例如,`TGenerator`接口定义了协程的基本操作,包括`Resume`用于恢复协程执行,`Suspend`用于挂起协程,以及`Finished`属性来检查协程是否已结束。 在压缩包文件`DCoroutine-master`中,我们可以预期找到一个实现...

    unity通过协程实现异步下载数据并加载

    为了不阻塞游戏主循环,Unity3D引入了协程(Coroutine)的概念,允许开发者以非阻塞的方式处理长时间运行的任务,比如下载和加载资源。 **协程简介** 协程是一种轻量级的线程,它不像传统的多线程那样需要频繁地上...

    Python-异步协程下载器

    在Python编程领域,异步协程(Asyncio)是一种高效处理并发任务的机制,尤其适用于I/O密集型应用,如网络下载。本项目"Python-异步协程下载器"显然是利用了Python的异步特性来实现一个高效的文件下载工具。下面我们...

    libco协程库,附VS工程

    libco是微信后台大规模使用的c/c++协程库。 libco的特性 无需侵入业务逻辑,把多进程、多线程服务改造成协程服务,并发能力得到百倍提升; 支持CGI框架,轻松构建web服务(New); 支持gethostbyname、mysqlclient、ssl...

    Unity3d协程实现

    Unity3D是一款强大的跨平台游戏开发引擎,而协程(Coroutine)是Unity中一个非常重要的概念,它允许开发者在执行过程中暂停和恢复一个函数,而不是一次性执行完毕。这对于实现复杂的逻辑,如动画过渡、延时操作、...

    go 实现的通用协程池

    在Golang中,协程(goroutine)是并发执行的轻量级线程,它们使得程序能够并行处理多个任务,极大地提高了效率。而协程池(Coroutine Pool)则是一种管理协程的机制,用于控制并发量,防止过多的协程同时运行导致...

    python协程.pptx

    Python 协程是一种轻量级的并发机制,它允许单线程内的多个任务协作执行,而无需线程切换带来的开销。协程的核心在于 `yield` 关键字,它使得函数能够暂停执行并保存状态,之后可以从暂停的地方继续。协程在语法上与...

    Kotlin协程分析(一)——协程的创建过程和执行过程.pdf

    Kotlin协程是一种轻量级的并发机制,它允许开发者编写非阻塞式的代码来处理异步操作,从而提高程序的执行效率。协程的工作原理是通过挂起和恢复函数来控制执行流程,而不是像线程那样进行上下文切换。在Kotlin 1.4.0...

    Android-根据kotlin的协程设计简单实现java的协程设计并且提供kotlin版本和java版本

    在Android开发中,Kotlin的协程是一种强大的工具,它能帮助开发者解决异步编程中的复杂性和回调地狱问题。协程允许我们以同步的方式编写异步代码,提高代码的可读性和可维护性。本项目的目标是根据Kotlin的协程设计...

    Unity3D技术之Unity3D中的协程(Coroutine)详解.docx

    本文将详细介绍 Unity3D 中的协程(Coroutine)技术,包括为什么需要协程、协程的定义和工作原理、如何使用协程等方面的知识点。 一、为什么需要协程 在游戏中,有许多过程需要花费多个逻辑帧去计算。如果我们不...

    Android-协程kotlinretrofitmvvm的模式

    Kotlin的协程提供了异常处理机制,可以在协程块中捕获并处理错误。 在名为"MVVMDemo-master"的项目中,我们可以看到一个实际应用这些概念的例子。这个项目包含了Kotlin的使用,Retrofit的API调用,以及MVVM架构的...

    基于Golang协程实现流量统计系统视频.zip

    第3章Go的协程rar 第4章示例环境搭建ram 第5章Go批里生成日志ar 第6章统计系统框架构成.rar 第7章统计统之口志费.rar 第8章统计系统之批星解析a 第9章统计系统之统计逻辑,rar 第10统计系统之存储器rar 第11章据可视...

    Android使用ksoap2+协程+handler实现WebService

    本示例主要探讨如何在Android应用中利用kotlin的协程(Coroutines)和ksoap2库来实现对WebService的调用,并解决在API 30及以上版本中Handler过时的问题。 一、ksoap2库介绍 ksoap2是一个轻量级的开源库,专为...

    Unity协程(Coroutine)原理深入剖析

    Unity协程(Coroutine)是Unity引擎中的一个强大特性,它允许开发者在游戏逻辑中实现非阻塞式的长时间运行任务,比如动画播放、网络同步、定时器等。在Unity中,协程是由`IEnumerator`接口定义的,这与C#中的迭代器...

Global site tag (gtag.js) - Google Analytics