當前位置:
首頁 > 最新 > 協程-以Python和Go為例

協程-以Python和Go為例

進程、線程和協程進程的定義:

進程,是計算機中已運行程序的實體。程序本身只是指令、數據及其組織形式的描述,進程才是程序的真正運行實例。

線程的定義:

操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。

進程和線程的關係:

一條線程指的是進程中一個單一順序的控制流,一個進程中可以並發多個線程,每條線程並行執行不同的任務。

協程的定義:

協程通過在線程中實現調度,避免了陷入內核級別的上下文切換造成的性能損失,進而突破了線程在IO上的性能瓶頸。

協程和線程的關係

協程是在語言層面實現對線程的調度,避免了內核級別的上下文消耗。

Python的協程

Python的協程源於yield指令。yield有兩個功能:

yield item用於產出一個值,反饋給next()的調用方。

作出讓步,暫停執行生成器,讓調用方繼續工作,直到需要使用另一個值時再調用next()。

協程是對線程的調度,yield類似惰性求值方式可以視為一種流程式控制制工具,實現協作式多任務。協程的yield語句寫在表達式右邊(func = yield),可以產出值,也可以不產出值,如果yield後面沒有表達式,則生成器產出None。協程也可以從調用方接受數據如send(data)。

在語言層面對協程的引用來源於pep342,pep342詳細介紹了協程的使用:

Coroutines are a natural way of expressing many algorithms, such as simulations, games, asynchronous I/O, and other forms of event-driven programming or co-operative multitasking.

重要的幾點大概如下:

Redefine yield to be an expression, rather than a statement。

將yield視為一個表達式而不是一個指令

Add a new send() method for generator-iterators, which resumes the generator and sends a value that becomes the result of the current yield-expression.

增加send方法啟動生成器和發送值

Add a new throw() method for generator-iterators, which raises an exception at the point where the generator was paused, and which returns the next value yielded by the generator, raising StopIteration if the generator exits without yielding another value.

增加throw方法拋出異常

Add a close() method for generator-iterators, which raises GeneratorExit at the point where the generator was paused.

增加close方法用於退出

在Python3.5正式引入了 Async/Await表達式,使得協程正式在語言層面得到支持和優化,大大簡化之前的yield寫法。

例如:

Go的協程

Go的協程是天生在語言層面支持,和Python類似都是採用了關鍵字,而Go語言使用了go這個關鍵字,可能是想表明協程是Go語言中最重要的特性。

但是上面的程序並不會列印出結果,因為程序沒有等待Add函數結束,就已經結束了。而協程之間的通信,Go採用了channel關鍵字。

協程的調度理論模型

協程的思想源於進程和協程都是屬於系統內核級的,開銷特別巨大,並且在併發模式下需要各種各樣的鎖來保證程序運行正常。後來在Node.js里引入了基於回調的非阻塞/非同步IO,但是給開發者帶來了無盡的「回調地獄」:

也正是因為如此「醜陋」的代碼存在,Python和Go引入了消息調度系統模型,也就是協程,來避免鎖的影響和進程/線程開銷大的問題。協程從本質上來說是一種用戶態的線程,不需要系統來執行搶佔式調度,而是在語言層面實現線程的調度。具體的消息調度模型可以參考我之前寫的文章Actor模型速覽。

因為協程不再使用共享內存/數據,而是使用通信來共享內存/鎖,因為在一個超級大系統里具有無數的鎖,共享變數等等會使得整個系統變得無比的臃腫,而通過消息機制來交流,可以使得每個並發的單元都成為一個獨立的個體,擁有自己的變數,單元之間變數並不共享,對於單元的輸入輸出只有消息。開發者只需要關心在一個並發單元的輸入與輸出的影響,而不需要再考慮類似於修改共享內存/數據對其它程序的影響。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python 的精彩文章:

Python碼農福音,GitHub增加Python語言安全漏洞告警
Python框架:Django寫圖書管理系統

TAG:Python |