什麼是協程 ?

最近更新比較少,心裏十分的愧疚,實在是太忙了!向各位讀者說句抱歉。python

今天要講的這個東西說實話,我也是今天才知道,一個咱們大多數人可能歷來都沒用過的語法,哪就是傳說中的【協程 Coroutine】。git

可能你會說,攜程誰不知道啊,不就是哪一個用來訂機票訂酒店的軟件麼,這有什麼好學的!這樣的話你就錯了,此協程非彼攜程,可不要傻傻分不清楚嘍!github

什麼是進程和線程

進程是什麼

直白地講,進程就是應用程序的啓動實例。好比咱們運行一個遊戲,打開一個軟件,就是開啓了一個進程,進程擁有代碼和打開的文件資源、數據資源、獨立的內存空間。編程

線程又是什麼

線程從屬於進程,是程序的實際執行者。一個進程至少包含一個主線程,也能夠有更多的子線程,線程擁有本身的棧空間。微信

線程具備五種狀態:多線程

file

對操做系統來講,線程是最小的執行單元,進程是最小的資源管理單元。架構

不管進程仍是線程,都是由操做系統所管理的。併發

進程和線程的痛點

線程之間是如何進行協做的呢?框架

最經典的例子就是生產者/消費者模式異步

若干個生產者線程向隊列中寫入數據,若干個消費者線程從隊列中消費數據。

什麼是協程

官方定義以下:

A coroutine is a function that can suspend its execution (yield) until the given given YieldInstruction finishes.

用我蹩腳的英語來翻譯一下就是:

協程是一種能夠暫停執行過程的函數,它能夠中斷當前的執行過程直到下一個 Yield 指令達成。

個人理解是能夠把它當成爲相似 於CPU 在多個進程間切換,從而達到多個進程同時執行的效果。協程是一種比線程更加輕量級的存在,一個進程能夠擁有多個線程,一個線程也能夠擁有多個協程。

學過計算機組成原理的都知道,當 CPU 在多個進程間切換時,那些後臺程序就會處於這種暫停用英文的 Suspend 或許更恰當)的狀態,因此早年的電腦即便用一個 CPU 也能夠同時處理多個進程任務,這是一種「僞多線程」的技術。

除此以外比較重要的一點是,協程不是被操做系統內核所管理,而徹底是由程序所控制(也就是在用戶態執行)。這樣帶來的好處就是性能獲得了很大的提高,不會像線程那樣須要上下文切換來消耗資源,所以協程的開銷遠遠小於線程的開銷

注意,這裏要劃一個重點,協程是一種「僞多線程」,始終記得這一點,能夠幫助咱們來理解協程會這個概念。

協程函數的寫法

Java 語言並無對協程提供原生支持,因此用 Java 暫時還演示不了,可是有個開源框架基本模擬除了協程的功能,感興趣的朋友能夠去看看源碼。。。

地址 :https://github.com/kilim/kilim

Go 語言根據我查詢資料來看,對於協程的支持超乎個人想象,能夠說是強大而簡潔,輕輕鬆鬆分分鐘建立成百上千個協程併發執行。

func Add(x, y int) {
    z := x + y
    fmt.Println(z)
}
 
func main() {
    for i:=0; i<10; i++ {
        go Add(i, i)
    }
}

如上代碼,在一個函數調用前加上 go 關鍵字,此次調用就會在一個新的協程中併發執行。當被調用的函數返回時,這個協程也自動結束。須要注意的是,若是這個函數有返回值,那麼這個返回值會被丟棄。

Python 語言也能夠經過 yield/send 的方式實現協程。在 python 3.5 之後,async/await 成爲了更好的替代方案。

def consume():
    while True:
        # consumer 協程等待接收數據
        number = yield
        print("開始消費",number) 
        
consumer = consume()
# 讓初始化狀態的 consumer 協程先執行起來,在 yield 處中止
next(consumer)
for num in range(0,100)
    print("開始生產",num)
    # 發送數據給 consumer 協程
    consumer.send(num)

其餘語言的寫法我也就不寫了,畢竟不太熟,寫了怕誤人子弟!!!

總結

根據今天查閱的資料來看,協程的應用場景主要在於 :I/O 密集型任務。

這一點與多線程有些相似,但協程調用是在一個線程內進行的,是單線程,切換的開銷小,所以效率上略高於多線程。當程序在執行 I/O 時操做時,CPU 是空閒的,此時能夠充分利用 CPU 的時間片來處理其餘任務。在單線程中,一個函數調用,通常是從函數的第一行代碼開始執行,結束於 return 語句、異常或者函數執行(也能夠認爲是隱式地返回了 None )。 有了協程,咱們在函數的執行過程當中,若是遇到了耗時的 I/O 操做,函數能夠臨時讓出控制權,讓 CPU 執行其餘函數,等 I/O 操做執行完畢之後再收回控制權。

簡單來說協程的好處:

  • 跨平臺
  • 跨體系架構
  • 無需線程上下文切換的開銷
  • 無需原子操做鎖定及同步的開銷
  • 方便切換控制流,簡化編程模型
  • 高併發+高擴展性+低成本:一個CPU支持上萬的協程都不是問題。因此很適合用於高併發處理。

缺點:

  • 沒法利用多核資源:協程的本質是個單線程,它不能同時將 單個CPU 的多個核用上,協程須要和進程配合才能運行在多CPU上.固然咱們平常所編寫的絕大部分應用都沒有這個必要,除非是cpu密集型應用。
  • 進行阻塞(Blocking)操做(如IO時)會阻塞掉整個程序:這一點和事件驅動同樣,可使用異步IO操做來解決

最後再貼個圖來總結一下,更清楚:

本文首發於微信公衆號 【程序猿雜貨鋪】,關注公衆號,獲取更多精彩文章!
歡迎關注個人公衆號

相關文章
相關標籤/搜索