协程
############################# 协 程 #######################################
进程 : 资源分配的最小单位 ,班级
线程: cpu调度最小单位 , 人
什么是协程? 一个人分八半
协程 :能在一条线程的基础上,在多个任务之间互相切换
节省了线程的开启的消耗
是从python代码的级别调度的
正常的线程是CPU调度的最小单位
协程的调度并不是由操作系统来完成的
在两个任务之间互相切换-协程 def func(): print(1) x = yield 'aaa' print(x) yield 'bbb' g = func() print(next(g)) ##接收的返回值 print(g.send(****)) ##传给了x #得到结果: 1 aaa **** bbb 在多个函数之间互相切换的功能 -协程 def consumer(): while True: x = yield print(x) def producer(): g = consumer() next(g) #预激 for i in range(10): g.send(i) producer() yield 只有程序之间的切换,没有重利用任何IO操作的时间
需要强调的是:
#1.python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到io或执行时间过长就会*交出cpu执行权限,切换其他线程运行) #2.单线程内开启协程,一旦遇到io,就会从应用程序级别(而非操作系统)控制切换,以此来提升效率(!!!非io操作的切换与效率无关)
对比操作系统控制线程的切换,用户在单线程内控制协程的切换
优点: #1,协程的切换开销更小, 属于程序级别的切换,操作系统完全感知不到,因而更加轻量级 #2,单线程内就可以实现并发的效果,最大限度的利用cpu 缺点: #1,协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程 #2,协程指的是单个线程,因而一旦协程出现阻塞,将会则色整个线程
总结协程特点:
1.必须在只有一个单线程里实现并发
2.修改共享数据不需加锁
3.用户程序里自己保存多个控制流的上下文栈
4.附加:一个协程遇到IO操作自动切换到其他协程(如何实现检测IO,yield,greenlet都无法实现,就用到了gevent模块(select机制))
Greenlet模块
安装 pip3 install greenlet
import time from greenlet import greenlet # 协程模块 # 单纯的程序切换耗费时间 def eat(): print('吃') time.sleep(1) g2.switch() # 切换 print('吃完了') time.sleep(1) g2.switch() def play(): print('玩儿') time.sleep(1) g1.switch() print('玩儿美了') time.sleep(1) g1 = greenlet(eat) g2 = greenlet(play) g1.switch() # 切换