Goroutine(協程)爲什麼能處理大併發?

簡單來講:協程十分輕量,能夠在一個進程中執行有數以十萬計的協程,依舊保持高性能。html

進程、線程、協程的關係和區別:程序員

  • 進程擁有本身獨立的堆和棧,既不共享堆,亦不共享棧,進程由操做系統調度。安全

  • 線程擁有本身獨立的棧和共享的堆,共享堆,不共享棧,線程亦由操做系統調度(標準線程是的)。多線程

  • 協程和線程同樣共享堆,不共享棧,協程由程序員在協程的代碼裏顯示調度。併發

堆和棧的區別請參看:http://www.cnblogs.com/ghj1976/p/3623037.html 框架

協程和線程的區別是:協程避免了無心義的調度,由此能夠提升性能,但也所以,程序員必須本身承擔調度的責任。函數

 

執行協程只須要極少的棧內存(大概是4~5KB),默認狀況下,線程棧的大小爲1MB。性能

goroutine就是一段代碼,一個函數入口,以及在堆上爲其分配的一個堆棧。因此它很是廉價,咱們能夠很輕鬆的建立上萬個goroutine,但它們並非被操做系統所調度執行。spa

和全部其餘併發框架裏的協程同樣,goroutine裏所謂「無鎖」的優勢只在單線程下有效,若是$GOMAXPROCS > 1而且協程間須要通訊,Go運行庫會負責加鎖保護數據,這也是爲何sieve.go這樣的例子在多CPU多線程時反而更慢的緣由.操作系統

 

http://my.oschina.net/Obahua/blog/144549

goroutine 的一個主要特性就是它們的消耗;建立它們的初始內存成本很低廉(與須要 1 至 8MB 內存的傳統 POSIX 線程造成鮮明對比)以及根據須要動態增加和縮減佔用的資源。這使得 goroutine 會從 4096 字節的初始棧內存佔用開始按需增加或縮減內存佔用,而無需擔憂資源的耗盡。

爲了實現這個目標,連接器(5l、6l 和 8l)會在每一個函數前插入一個序文,這個序文會在函數被調用以前檢查判斷當前的資源是否知足調用該函數的需求(備註 1)。若是不知足,則調用 runtime.morestack 來分配新的棧頁面(備註 2),從函數的調用者那裏拷貝函數的參數,而後將控制權返回給調用者。此時,已經能夠安全地調用該函數了。當函數執行完畢,事情並無就此結束,函數的返回參數又被拷貝至調用者的棧結構中,而後釋放無用的棧空間。

經過這個過程,有效地實現了棧內存的無限使用。假設你並非不斷地在兩個棧之間往返,通俗地講叫棧分割,則代價是十分低廉的。

 

參考資料:

【翻譯】爲何 goroutine 的棧內存無窮大? 
http://my.oschina.net/Obahua/blog/144549

進程、線程和協程的理解 
http://blog.leiqin.name/2012/12/02/%E8%BF%9B%E7%A8%8B%E3%80%81%E7%BA%BF%E7%A8%8B%E5%92%8C%E5%8D%8F%E7%A8%8B%E7%9A%84%E7%90%86%E8%A7%A3.html

協程框架的堆棧大小陷阱 
http://blog.csdn.net/huyiyang2010/article/details/6104891

Coroutine及其實現 
http://www.cnblogs.com/foxmailed/archive/2014/01/08.html

goroutine背後的系統知識 
http://www.sizeofvoid.net/goroutine-under-the-hood/

相關文章
相關標籤/搜索