协程,英文为coroutine,也被称作轻量级线程或者微线程,是一种用户态的轻量级线程。协程的执行不是由系统内核来调度,而是由用户程序自行控制。这意味着协程的切换非常快,几乎只涉及到几个寄存器的内容变更。
协程的主要思想是控制权来回切换,在函数执行过程中,如果遇到了等待IO操作,程序会暂时将控制权交回给用户,用户可以控制协程切换到其他函数执行,等到IO操作完成后,再通过某种方式将控制权交回原来的协程,继续执行。这种切换过程相比于线程的上下文切换开销非常小。
进程、线程和协程是操作系统中处理任务的基本单位,它们有以下区别:
python代码:
# 协程
# 进程,操作系统中存在
# 线程,操作系统中存在
# 协程,是由程序员创造出来的一个不是真实存在的东西
# 协程:是微线程,对一个线程程序分片,使得线程在代码块之间来回切换执行,不是在原来遂行执行
import greenlet
def f1():
print(11)
gr2.switch()
print(22)
gr2.switch()
def f2():
print(33)
gr1.switch()
print(44)
# 协程1
gr1=greenlet.greenlet (f1)
# 协程2
gr2=greenlet.greenlet (f2)
gr1.switch()
# 单纯的协程无用,而且会降低性能(来回切换)
print("#######################")
def f11():
print(11)
print(33)
def f22():
print(22)
print(44)
f11()
f22()
运行结果;
虽然协程可以使得单线程内的并发性提高,但是它本身并不能实现真正的并发。因为在一个时间点,只有一个协程在执行。要想实现真正的并发,通常会使用多线程或多进程。但是,对于IO密集型任务,使用协程结合事件循环的异步非阻塞框架可以获得更高的性能。这是因为,相比于线程和进程,协程在切换时的开销非常小。
注意:单纯的协程无用,而且会降低性能(来回切换)
在单线程中实现并发的一种方式是使用协程+IO切换的方式,例如使用Python的gevent库。另一种方式是使用基于事件循环的异步非阻塞框架,例如Twisted。这两种方式都可以实现在单线程中提高程序的并发性能。
协程+IO切换 实现单线程提供并发:
# 协程+遇到IO就切换=>才有意义
from gevent import monkey
monkey.patch_all()
#以后代码中遇到I0,都会自动执行greenlet的switch,进行切换
import requests
import gevent
def get_page1(url):
ret = requests.get(url)
print(url,ret.content)
def get_page2(url):
ret = requests.get(url)
print(url,ret.content)
def get_page3(url):
ret = requests.get(url)
print(url,ret.content)
gevent.joinall([ gevent.spawn(get_page1, 'https://www.python.org/'),#协程1
gevent.spawn(get_page2, 'https://www.yahoo.com/'),#协程2
gevent.spawn(get_page3, 'https://github.com/'),]) #协程3
# 1.什么是协程? # 协程也可以称为“微线程”,就是开发者控制线程执行 # 控制先执行某段代码,然后再切換到另外函数执行,来回切换 # 2.协程可以提高并发? # 协程自己本身无法实现并发(甚至性能会降低)。 # 协程+IO切换,性能提高。 # 3.进程、线程、协程的区别? # 4.単线程提供井发: # -协程+IO切换:gevent # -基于事件循环的异歩非阻塞框架:Twisted