组团学

Python协程

阅读 (216352)

一、概念

  • 子程序

    在所有的语言中都是层级调用的,比如A中调用B,B在执行过程中调用C,C执行完返回,B执行完返回,最后是A执行完毕。这是通过栈实现的,一个函数就是一个执行的子程序,子程序的调用总是有一个入口、一次返回,调用的顺序是明确的

  • 协程

    又称微线程(纤程),是一种用户态的轻量级线程

  • 理解协程

    普通理解:线程是系统级别的,它们是由操作系统调度。协程是程序级别,由程序员根据需求自己调度。我们把一个线程中的一个个函数称为子程序,那么一个子程序在执行的过程中可以中断去执行别的子程序,这就是协程。也就是说同一个线程下的一段代码1执行执行着就中断,然后去执行另一段代码2,当再次回来执行代码1时,接着从之前的中断的位置继续向下执行

    专业理解:协程拥有自己的寄存器上下文和栈,协程在调度切换时,将寄存器上下文和栈保存到其他的地方,在切换回来时,恢复先前保存的寄存器上下文和栈。因此,协程能后保留一次调用的状态,每次过程重入时,就相当于进入上一次调用的状态

  • 优点

    a、无需线程上下文切换的开销,协程避免了无意义的调度,从而提高了性能,但是程序员必须自己承担调度的任务,同时协程也失去了标准线程使用多CPU的能力

    b、无需原子操作锁定及同步的开销

    c、方便切换控制流,简化编程模型

    d、高并发+高可扩展+低成本:一个CPU支持上万个协程不是问题

  • 缺点

    a、无法利用多核CPU,协程的本质是单个线程,它不能同时将多个CPU的多个核心使用上,协程需要和进程匹配使用才能运行在多个CPU上。但是一般不需要,除非是CPU计算密集型的应用

    b、进行阻塞操作(操作IO)会阻塞整个程序

  • 代码

    def run1(): print(1) print(2) print(3) print(4) def run2(): print("a") print("b") print("c") print("d") run1() run2()
  • 结果

    正常结果

    1
    2
    3
    4
    a
    b
    c
    d
    

    协程实现的结果(假设)

    1 a b 2 3 c 4 d

二、数据传递

  • 数据传递

    def func(): print("------------------1") r = yield 1 print("------------------2", r) yield 2 print("------------------3") yield 3 print("------------------4") yield 4 print("------------------5") yield 5 g = func() # print(next(g)) # print(next(g)) # print(next(g)) # print(next(g)) # print(next(g)) # 启动生成器g,从第二个开始send的参数值会放到yield处 print(g.send(None)) print(g.send(11))
  • 生产者与消费者

    import time def product(c): print("启动生产者……") #启动消费者 c.send(None) for data in ["good", "nice", "cool", "handsome"]: print("生产出%s数据"%(data)) #将数据交给消费者 c.send(data) time.sleep(2) #关闭消费者 c.close() print("结束生产者……") def customer(): print("启动消费者……") while True: print("等待生产者生产数据") #获取数据 value = yield print("消费了%s"%value) c = customer() product(c)
需要 登录 才可以提问哦