协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是协程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。
1. 目标:
在线程下实现并发
并发(多个任务看起来是同时执行就是并发):切换+保存状态
2. 协程:
协程是单线程实现并发
注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念(操作系统调度的是线程)
在单线程下实现多个任务间遇到IO就切换就可以降低单线程的IO时间,从而最大限度地提升单线程的效率
总结协程特点:
1 .在一个单线程里实现并发
2 .修改共享数据不需加锁
3 .用户程序里自己保存多个控制流的上下文栈
附加:一个协程遇到IO操作自动切换到其它协程(如何实现检测IO,yield、greenlet都无法实现,就用到了gevent模块(select机制))
#串行执行
import time
def func1():
for i in range(10000000):
i+1
def func2():
for i in range(10000000):
i+1
start = time.time()
func1()
func2()
stop = time.time()
print(stop - start) # 所需时间:1.1090044975280762
#基于yield并发执行
import time
def func1():
while True:
yield
def func2():
g=func1()
for i in range(10000000):
i+1
next(g)
start=time.time()
func2()
stop=time.time()
print(stop-start) # 所需时间:1.6645479202270508
从上面代码中可以知道在单线程下,如果是计算密集型代码,使用yield并发执行,相对于串行执行并不能提高效率,反而会降低效率.
IO密集型:
#基于yield并发执行
import time
def func1():
while True:
print('func1')
yield
def func2():
g=func1()
for i in range(10000000):
print('func2')
time.sleep(100)
i+1
next(g)
start=time.time()
func2()
stop=time.time()
print(stop-start)
经过测试可以得知yield不会遇到IO就切换,所有说yelid方法pass,进而引出gevent模块
gevent模块
安装gevent模块,在cmd窗口中输入 pip3 install gevent
(前提是安装了python3 并且配置好了环境变量)
from gevent import monkey;monkey.patch_all()
from gevent import spawn,joinall
import time
def play(name):
print('%s play 1' %name)
time.sleep(5)
print('%s play 2' %name)
def eat(name):
print('%s eat 1' %name)
time.sleep(3)
print('%s eat 2' %name)
start=time.time()
g1=spawn(play,'HGQ')
g2=spawn(eat,'HGQ')
# g1.join()
# g2.join()
joinall([g1,g2])
print('主',time.time()-start)
网友评论