協程,又稱微線程,纖程。英文名Coroutine。協程是一種用戶態的輕量級線程。協程擁有本身的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其餘地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。所以:協程能保留上一次調用時的狀態,每次過程重入時,就至關於進入上一次調用的狀態,換種說法:進入上一次離開時所處邏輯流的位置。python
PS: "原子操做(atomic operation)是不須要synchronized",所謂原子操做是指不會被線程調度機制打斷的操做;這種操做一旦開始,就一直運行到結束,中間不會有任何 context switch (切換到另外一個線程)。原子操做能夠是一個步驟,也能夠是多個操做步驟,可是其順序是不能夠被打亂,或者切割掉只執行部分。視做總體是原子性的核心。編程
以前咱們有用過yield關鍵字將用過函數變成一個生成器,實現了在單線程狀況下的併發效果,以下例所示:併發
import time import queue def consumer(name): print("--->starting eating baozi...") while True: new_baozi = yield print("[%s] is eating baozi %s" % (name,new_baozi)) time.sleep(1) def producer(): r = con.__next__() r = con2.__next__() n = 0 while n < 5: n +=1 con.send(n) con2.send(n) print("\033[32;1m[producer]\033[0m is making baozi %s" %n ) if __name__ == '__main__': con = consumer("c1") con2 = consumer("c2") p = producer()
那麼這算不算協程呢?咱們先要知道到底知足什麼條件纔算是一個協程。異步
若是知足了以上的條件咱們就能夠認爲是一個協程。因此yield並徹底算是一個協程,由於它不能實現遇到IO操做就自動切換到其餘協程的功能。ide
greenlet是一個用C實現的協程模塊,相比與python自帶的yield,它可使你在任意函數之間隨意切換,而不需把這個函數先聲明爲generator。異步編程
from greenlet import greenlet def test1(): print(12) gr2.switch() print(34) gr2.switch() def test2(): print(56) gr1.switch() print(78) gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch() 執行結果: 12 56 34 78
可是這個模塊沒有解決一個問題,就是自動切換IO操做,上面的切換是咱們人爲手動切換的。函數
Gevent 是一個第三方庫,能夠輕鬆經過gevent實現併發同步或異步編程,在gevent中用到的主要模式是Greenlet, 它是以C擴展模塊形式接入Python的輕量級協程。 Greenlet所有運行在主程序操做系統進程的內部,但它們被協做式地調度。高併發
import gevent def func1(): print('\033[31;1m我是func1的1\033[0m') gevent.sleep(2) print('\033[31;1m我是func1的2\033[0m') def func2(): print('\033[32;1m我是func2的1\033[0m') gevent.sleep(1) print('\033[32;1m我是func2的2\033[0m') def func3(): print('\033[32;1m我是func3的1\033[0m') gevent.sleep(0) print('\033[32;1m我是func3的2\033[0m') gevent.joinall([ gevent.spawn(func1), gevent.spawn(func2), gevent.spawn(func3), ]) 輸出結果: 我是func1的1 我是func2的1 我是func3的1 我是func3的2 我是func2的2 我是func1的2