跳转至

Python-:协程-生成器实现

协程

  • 一句话解释就是: 单线程执行多任务
  • 协程是线程的更小切分, 又称作'微线程':线程是系同级别的,是有操作系统调度, 而协程是程序级别的,使我们自己设置的规则调度
  • 协程的概念: 在一个线程中会有很多的函数, 姑且就称为子程序吧, 在子程序执行的过程中,我们可以按照逻辑子程序执行正在执行的函数,让其执行其他的子程序,执行一段时间后,继续执行原来的子程序,且还是从原来中断的地方继续执行,类似 yield 的操作总之就是来回切换
  • 协程无法利用多核资源(单进程单线程)
  • 协程占用的资源小,切换效率高,一个CPU同时支持上万的协程都无压力

和线程的区别

相同点

  • 协程在工作是和CPU在并发执行多个进程差不多,是通过轮转在进程之间来回切换,操作系统实现这种交错执行的机制是上下文切换: 栈(切换之前保存变量函数的调用),寄存器状态(用于执行流恢复后要做什么)
  • 任何时刻 一个核心只能同时执行一个进程,当转移到新进程时,就要进行上下文切换(保存当前进程上下文,恢复新进程上下文,然后将控制权交给新进程),新进程就会从上次停止的地方开始

不同点

  • 进程是内核调度,协程是用户态保存恢复的
  • 进程会被强占(执行时被CPU强行切出),协程不存在如果协程不主动停止让出CPU则其他协程就没有执行的机会
  • 多协程的程序其实就是单进程,单线程
  • 协程只需要4k的栈就足够,进程占用的内存要大得多

Demo

import time
# 如果一个函数中定义包含 yield 的关键字, 那么这个函数不再是一个普通的函数, 而是一个生成器
def consumer(name): # 生成器
    print('{}, 要开始吃包子了'.format(name))
    while True:
        baozi = yield # 暂停, 记录位置, 返回跳出(接收下面send发送的数据,接收到数据后才会继续执行)
        print('包子{}, {}吃了'.format(baozi, name))

def producer(name)
    c = consumer('消费者') # 只是变成了一个生成器
    c.__next__() # next只是唤醒yield 不传递值
    for i in range(4):
        time.sleep(1)
        print('{}, 做了包子{}'.format(name, i))
        c.send(i)

if __name__ == '__main__'
    producer('消费者')