对于操作系统来说协程是不可见的,不需要操作系统调度
协程(greenlet 注:小写g):如果检测到线程进入到IO阻塞,就去执行这个线程中的其他任务,即在线程中的任务中来回切换。
协程对操作系统有负担吗?
答:操作系统负责创建线程,但线程中的任务执行由程序决定,所以协程对操作系统没有负担。(协程是程序级别的操作单位)
1.协程就像是状态之间的来回切换和保存,所以是不是跟以前学的yield很像呢?
import time
def consumer():
while True:
res = yield
def producer():
g = consumer() #切换到consumer
next(g)
for i in range(1000000):
g.send(i) #发送到yield,yield拿到后再返回到send,这样producrh和consumer之间来回
切换,像协程一样工作
start =time.time()
producer()
print(time.time() - start)
引子:协程任务之间切换(g.switch)
import time
from greenlet import greenlet
def play():
print("start paly")
g2.switch()
print("end play")
g2.switch()
def sleep():
print("start sleep")
g1.switch()
print("end sleep")
g1 = greenlet(play)
g2= greenlet(sleep)
g1.switch()
start paly
start sleep
end play
end sleep
Process finished with exit code 0
gevent 基于greenlet实现的,多个任务交给gevent管理,遇到IO就使用greenlet进行切换 (不识别除自身外的阻塞,如time.sleep())
from gevent import monkey;monkey.patch_all()
把下面所有的模块中的阻塞都打成一个包,然后gevent就可以识别这些阻塞事件了
from gevent import monkey;monkey.patch_all()
# 把下面所有的模块中的阻塞都打成一个包,然后gevent就可以识别这些阻塞事件了
import time
import gevent
def play(): # 协程1
print(time.time())
print('start play')
time.sleep(1)
print('end play')
def sleep(): # 协程2
print('start sleep')
print('end sleep')
print(time.time())
g1 = gevent.spawn(play)
g2 = gevent.spawn(sleep)
gevent.joinall([g1,g2]) #控制协程任务,执行完毕之后join立即结束阻塞
I/O多路复用
elect/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。它的流程如图:
异步I/O