併發編程-協程-20協程基礎

一丶yield

yield自己就是一種在單線程下能夠保存任務運行狀態的方法python

  1. yiled能夠保存狀態,yield的狀態保存與操做系統的保存線程狀態很像,可是yield是代碼級別控制的,更輕量級
  2. send能夠把一個函數的結果傳給另一個函數,以此實現單線程內程序之間的切換

計算密集型

# 單純地切換反而會下降運行效率
# 串行執行
import time
def consumer(res):
    '''任務1:接收數據,處理數據'''
    pass

def producer():
    '''任務2:生產數據'''
    res=[]
    for i in range(10000000):
        res.append(i)
    return res

start=time.time()
# 串行執行
res=producer()
consumer(res) #寫成consumer(producer())會下降執行效率
stop=time.time()
print(stop-start) #1.5536692142486572



# 基於yield併發執行
import time
def consumer():
    '''任務1:接收數據,處理數據'''
    while True:
        x=yield

def producer():
    '''任務2:生產數據'''
    g=consumer()
    next(g)
    for i in range(10000000):
        g.send(i)

start=time.time()
# 基於yield保存狀態,實現兩個任務直接來回切換,即併發的效果
# PS:若是每一個任務中都加上打印,那麼明顯地看到兩個任務的打印是你一次我一次,即併發執行的.
producer()

stop=time.time()
print(stop-start) #2.0272178649902344

IO密集型

# yield沒法作到遇到io阻塞
import time
def consumer():
    '''任務1:接收數據,處理數據'''
    while True:
        x=yield

def producer():
    '''任務2:生產數據'''
    g=consumer()
    next(g)
    for i in range(10000000):
        g.send(i)
        time.sleep(2)

start=time.time()
producer() #併發執行,可是任務producer遇到io就會阻塞住,並不會切到該線程內的其餘任務去執行

stop=time.time()
print(stop-start)

問題:

併發執行,可是任務producer遇到io就會阻塞住,並不會切到該線程內的其餘任務去執行併發

二丶什麼是協程

協程:是單線程下的併發

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

它本質就是在單線程下,由用戶本身控制一個任務遇到io阻塞了就切換另一個任務去執行,以此來提高效率。函數

三丶協程優缺點

優勢

  1. 協程的切換開銷更小,屬於程序級別的切換,操做系統徹底感知不到,於是更加輕量級
  2. 單線程內就能夠實現併發的效果,最大限度地利用cpu

缺點

  1. 協程的本質是單線程下,沒法利用多核,能夠是一個程序開啓多個進程,每一個進程內開啓多個線程,每一個線程內開啓協程
  2. 協程指的是單個線程,於是一旦協程出現阻塞,將會阻塞整個線程

總結協程特色:操作系統

  1. 必須在只有一個單線程裏實現併發
  2. 修改共享數據不需加鎖
  3. 用戶程序裏本身保存多個控制流的上下文棧
  4. 附加:一個協程遇到IO操做自動切換到其它協程(如何實現檢測IO,yield、greenlet都沒法實現,就用到了gevent模塊(select機制))
相關文章
相關標籤/搜索