协程,又叫微线程或者纤程。协程一般运行在语言的runtime或者虚拟机当中。操作系统层面上讲,协程可以叫做用户级线程,它与系统级线程之间的关系是多对多的,线程之间的切换和调度依赖程序或者语言本身,而不是操作系统。这种调度方式大大降低了操作系统的压力,在编程方面,协程避免了显示加锁操作。
在Python
中,yield
关键字能中止当前代码运行,相当于协调调度让出CPU资源,从而实现协程。
def consumer():
while True:
line = yield
# do some process
def productor():
while open_db('some_source') as f:
for k, v in enumerate(f):
yield v
print 'process line {}'.format(str(k))
c = consumer()
c.next()
for line in productor():
c.send(line)
上面这段代码中,consumer是一个生成器,接受yield的返回值,处理完数据之后在执行yield将cpu交给主程序。由于协程之间通过yield转交cpu控制权,所以不会出现想多线程抢占一样的结果乱序的情况。
除了原生语言层面的yield关键字之外,greenlet库对协程进行了更多的优化。greenlet由C语言写成,核心内容是PyGreenlet对象。每个PyGreenlet都单独开辟一个调用栈。
from greenlet import greenlet
def test1():
print 1
gr2.switch()
print 2
def test2():
print 3
gr1.switch()
print 4
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
上面代码从最后一行跳到test1,输出1,跳到test2,输出3,又跳回test1,输出2,gr1执行结束,4不会被输出。
由于GIL的限制,Python
本身无法做到真正的利用多核并行,但协程的使用可以在一定程度上减少IO密集应用导致的阻塞情况,相比单线程大大提升效率。