Goroutine 存在的意義是什么?
線程其實分兩種:
- 一種是傳統(tǒng)意義的操作系統(tǒng)線程
- 一種是編程語言實現的用戶態(tài)線程,也稱為協(xié)程,在 Go 中就是 goroutine
因此,goroutine 的存在必然是為了換個方式解決操作系統(tǒng)線程的一些弊端 -- 太重 。
太重表現在如下幾個方面:
第一:創(chuàng)建和切換太重
操作系統(tǒng)線程的創(chuàng)建和切換都需要進入內核,而進入內核所消耗的性能代價比較高,開銷較大;
第二:內存使用太重
一方面,為了盡量避免極端情況下操作系統(tǒng)線程棧的溢出,內核在創(chuàng)建操作系統(tǒng)線程時默認會為其分配一個較大的棧內存(虛擬地址空間,內核并不會一開始就分配這么多的物理內存),然而在絕大多數情況下,系統(tǒng)線程遠遠用不了這么多內存,這導致了浪費;
另一方面,棧內存空間一旦創(chuàng)建和初始化完成之后其大小就不能再有變化,這決定了在某些特殊場景下系統(tǒng)線程棧還是有溢出的風險。
相對的,用戶態(tài)的goroutine則輕量得多:
- goroutine是用戶態(tài)線程,其創(chuàng)建和切換都在用戶代碼中完成而無需進入操作系統(tǒng)內核,所以其開銷要遠遠小于系統(tǒng)線程的創(chuàng)建和切換;
- goroutine啟動時默認棧大小只有2k,這在多數情況下已經夠用了,即使不夠用,goroutine的棧也會自動擴大,同時,如果棧太大了過于浪費它還能自動收縮,這樣既沒有棧溢出的風險,也不會造成棧內存空間的大量浪費。