python 之協程
阿新 • • 發佈:2018-03-11
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 之協程