13、协程
一、概念
- 定义
- 协程本质上就是一条线程
- 协程可以把多个任务在一条线程来回切换
- 利用协程的特性可以把IO操作时的等待时间也利用起来,降低IO时间
- 切换并规避IO的模块
- gevent
- asyncio
- 进程、线程、协程
- 进程:数据隔离,数据不安全,开销很大,可以利用多核
- 由操作系统控制的
- 线程:数据共享,数据不安全,开销比较小,不能利用多核
- 线程是CPU层面控制的,有GIL锁,导致数据不安全
- 协程:数据共享,数据安全,开销最小,不能利用多核
- 由用户自己控制的,什么时候开始轮转GIL锁
- 进程:数据隔离,数据不安全,开销很大,可以利用多核
二、协程——gevent模块
-
协程与线程、进程不同之处
- 主线程(主进程)会等待所有的子线程(子进程)执行结束才会结束
- 主线程不会等待协程结束,当主程序结束之后所有的协程自动结束。,可以使用join或者joinall来阻塞主线程等待所有协程执行结束。
-
例子
-
要先安装gevent模块
-
from gevent import monkey
monkey.patch_all()这两个语句一定要放在最上面,不然可能出错
from gevent import monkey monkey.patch_all() import time import gevent def func(): #带有IO操作的内容写在func函数中 print('start func') time.sleep(1) print('end func') li=[] for i in range(40): g=gevent.spawn(func) #把func函数交给gevent.spawn执行 li.append(g) gevent.joinall(li) #制造阻塞,等所有协程执行完毕 -
-
等待所有的协程支持结束
-
join:阻塞一个
-
joinall:阻塞全部
-
-
利用gevent模块,实现socket并发
-
from gevent import monkey
monkey.patch_all()gevent默认识别不到系统级别的IO操作,这两句话作用让gevent识别到所有的IO
-
func函数就是一个协程处理函数
from gevent import monkey monkey.patch_all() import gevent import socket def func(conn): while True: ret=conn.recv(1024).decode('utf-8') ret=ret.upper() conn.send(ret.encode('utf-8')) sk=socket.socket() sk.bind(('127.0.0.1',9000)) sk.listen() #可以一直连接,每次连接之后都交给协程处理 while True: conn,_=sk.accept() gevent.spawn(func,conn)-
检测一个模块是否可以规避掉IO操作
import socket print(socket.socket) from gevent import monkey monkey.patch_all() import socket print(socket.socket) #结果如下 <class 'socket.socket'> <class 'gevent._socket3.socket'>- 两次结果不一样,表示gevent模块可以规避掉该IO操作
-
三、协程——asyncio模块
本文来自博客园,作者:majic_jie,转载请注明原文链接:https://www.cnblogs.com/majic-jie/articles/17546754.html

浙公网安备 33010602011771号