python 之协程

Posted jason-lin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 之协程相关的知识,希望对你有一定的参考价值。

协程:是单线程下的并发,又称微线程。

什么是线程?:

协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

协程的本质

协程的本质就是在单线程下,由用户自己控制一个任务遇到io阻塞了就切换另外一个任务去执行,以此来提升效率

对于不涉及io的操作,单纯的切换反而会降低效率

#并发执行
import time


def producer():
    g = consumer()
    next(g)
    for i in range(10000000):
        g.send(i)


def consumer():
    while True:
        res = yield


start_time = time.time()
producer()
stop_time = time.time()
print(stop_time-start_time)



#串行
import time

def producer():
    res=[]
    for i in range(10000000):
        res.append(i)
    return res


def consumer(res):
    pass


start_time=time.time()
res=producer()
consumer(res)
stop_time=time.time()
print(stop_time-start_time)

总结协程的优缺点:

优点

1、协程开销小,属于程序级别的切换,操作系统感知不到

2、单线程下可以实现并发效果, 最大限度地利用CPU

缺点

1、协程的本质是单线程下,无法利用多核优势。

2、协程是指单线程,一旦协程出现阻塞,将会阻塞整个线程。

协程的特点:

1、必须在一个单线程里实现并发

2、修改共享数据不加锁

3、用户程序自己控制保存上下文

4、一个协程遇到io操作自动切换到其他协程。

grennlet模块

并不能监听(不能遇到io自动切换)

from greenlet import greenlet
import time


def eat(name):
    print(‘%s eat 1‘ % name)
    time.sleep(10)
    g2.switch(‘egon‘)  # 切换
    print(‘%s eat 2‘ % name)
    g2.switch()


def play(name):
    print(‘%s play 1‘ % name)
    g1.switch()
    print(‘%s play 2‘ % name)


g1 = greenlet(eat)
g2 = greenlet(play)

g1.switch(‘egon‘)

gevent模块

#用法
g1=gevent.spawn(func,1,,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数eat的

g2=gevent.spawn(func2)

g1.join() #等待g1结束

g2.join() #等待g2结束

#或者上述两步合作一步:gevent.joinall([g1,g2])

g1.value#拿到func1的返回值

遇到io自动切换

import gevent
def eat(name):
    print(‘%s eat 1‘ %name)
    gevent.sleep(2)
    print(‘%s eat 2‘ %name)

def play(name):
    print(‘%s play 1‘ %name)
    gevent.sleep(1)
    print(‘%s play 2‘ %name)


g1=gevent.spawn(eat,‘egon‘)
g2=gevent.spawn(play,name=‘egon‘)
g1.join()
g2.join()
#或者gevent.joinall([g1,g2])
print(‘主‘)

以上是关于python 之协程的主要内容,如果未能解决你的问题,请参考以下文章

Python之协程函数

python之协程

python之协程

python 之协程

python之协程

Python 之协程