1. 程式人生 > >python 之協程

python 之協程

UC imp urn name 切換 tar cnblogs switch 用戶

協程:是單線程下的並發,又稱微線程。

什麽是線程?:

協程是一種用戶態的輕量級線程,即協程是由用戶程序自己控制調度的。

協程的本質

協程的本質就是在單線程下,由用戶自己控制一個任務遇到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 之協程