协程总结
原理+特点
- 协程本质就是线程,指在一条线程上来回切换以规避I/O操作
- 特点:数据共享,数据安全,不能利用多核,基于用户层面,开启/关闭花销时间比线程更少
- 但是需要用户自己设置所以只有当用户能明显感知的I/O操作才能被用户自己设置线程,而线程是自动感知系统的I/O操作
优点
- 可以减轻操作系统的压力,提高效率
- 可以给线程多设置几条协程,给线程造成一种很忙的样子,这样系统会多分配些时间片给线程,从而提高代码的执行效率
开启模块
- gevent模块
- 基于greenlet(C语言底层模块)完成切换+自动规避I/O功能
- asyncio模块
- 基于python底层语法(yeild等)完成切换+自动规避I/O功能
gevent模块
from gevent import monkey
monkey.patch_all() #用来识别所有的I/O操作
import time
import gevent
def func(): #带I/O操作的内容写在函数中,通过提交func交给gevent
print('start func')
time.sleep(1) #设置I/O操作
print('end func')
g1=gevent.spawn(func) #开启协程
g2=gevent.spawn(func)
g3=gevent.spawn(func)
g1.join()
g2.join()
g3.join()
# gevent.joinall([g1,g2,g3])
asyncio模块
import asyncio
import time
async def func(name):
# await关键字必须写在一个async函数里
print('start',name)
await asyncio.sleep(1)
#await后面必须接可能会发生阻塞的方法
print('end')
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([func('团团'),func('圆圆')])) #通过asyncio.await方法设置多个协程同时进行
# loop.run_until_complete(func('团团'))
# loop.run_until_complete(func('圆圆'))
进程/线程/协程比较
进程:数据隔离、数据不安全、可以使用多核、基于操作系统级别、开启/关闭花销时间大
线程:数据共享、数据不安全、不可以使用多核、基于操作系统级别、开启/关闭花销比进程小几百倍,线程可以系统自动规避I/O操作
协程:数据共享、数据不安全、不可以使用多核、基于用户级别、开启/关闭花销比线程更小,协程只能用户手动规避可以看得见的I/O操作
对于一个8核的cpu而言,开多少进程、线程、协程比较好?
进程数量:CPU数*1<进程数<CPU数*2 推荐开进程数量为CPU数量+1
线程数量:CPU数*5>=线程数
协程数量:500>=协程数
所以一个8核的cpu最多可开的并发数为(8*2)*(8*5)*500=320000,不推荐开这么多