協程
協程(Coroutine),又稱微線程,纖程,協程是一種用戶態的輕量級線程
協程擁有自己的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。因此協程能保留上一次調用時的狀態(即所有局部狀態的一個特定組合),每次過程重入時,就相當於進入上一次調用的狀態,換種說法:進入上一次離開時所處邏輯流的位置。
協程的優點
1.無需線程上下文切換的開銷
2.無需原子操作鎖定及同步的開銷
3.方便切換控制流,簡化編程模型
4.高並發+高擴展性+低成本:一個CPU支持上萬的協程都不是問題。所以很適合用於高並發處理
缺點
1.無法利用多核資源:協程的本質是個單線程,它不能同時將 單個CPU 的多個核用上,協程需要和進程配合才能運行在多CPU上.當然我們日常所編寫的絕大部分應用都沒有這個必要,除非是cpu密集型應用。
2.進行阻塞(Blocking)操作(如IO時)會阻塞掉整個程序
協程的實現
協程通過yield實現,或者通過其他三方的版本,如Greenlet,Gevent
1 from greenlet import greenlet 2 3 def test1(): 4 print (12) 5 gr2.switch() #使用switch進行切換 6 print (34) 7 gr2.switch() 8 9 def test2(): 10 print (56) 11 gr1.switch() 12 print (78) 13 14 gr1 = greenlet(test1) 15 gr2 = greenlet(test2) 16 gr1.switch()
1 import gevent 2 3 def foo(): 4 print('\033[32;1mRunning in foo\033[0m') 5 gevent.sleep(0) #遇到阻塞自動切換 6 print('\033[32;1mExplicit context switch to foo again\033[0m') 7 8 def bar(): 9 print('Explicit context to bar') 10 gevent.sleep(0) 11 print('Implicit context switch back to bar') 12 13 def ex(): 14 print('\033[31;1mExplicit context to ex\033[0m') 15 gevent.sleep(0) 16 print('\033[31;1mImplicit context switch back to ex\033[0m') 17 18 gevent.joinall([ 19 gevent.spawn(foo), 20 gevent.spawn(bar), 21 gevent.spawn(ex), 22 ])
事件驅動與異步IO
未完待續......